我正在创建一个Qt (使用SSL)服务器,多个客户端应该连接并使用DB,这是主要任务。因此,我认为我可以使用这个架构:每个客户端都有自己的线程,客户端通过DB连接池使用DB。
main.cpp:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyServer server;
server.listen(QHostAddress::Any, 1234);
return a.exec();
}没药。h:
class MyServer : public QTcpServer
{
Q_OBJECT
explicit MyServer(QObject *parent = 0);
~MyServer();
protected:
void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE;
signals:
void stopAll();
};myserver.cpp:
MyServer::MyServer(QObject *parent) : QTcpServer(parent)
{
//...
}
MyServer::~MyServer(){
emit stopAll();
}
void MyServer::incomingConnection(qintptr socketDescriptor){
QThread* clientThread = new QThread;
MyClient *client = new MyClient(socketDescriptor, this);
client->moveToThread(clientThread);
connect(clientThread, SIGNAL(started()), client, SLOT(process()));
connect(client, SIGNAL(finished()), clientThread, SLOT(quit()));
connect(this, SIGNAL(stopAll()), client, SLOT(stopFromServer()));
connect(client, SIGNAL(finished()), client, SLOT(deleteLater()));
connect(clientThread, SIGNAL(finished()), clientThread, SLOT(deleteLater()));
clientThread->start();
}我的客户:
class MyClient : public QObject
{
Q_OBJECT
public:
explicit MyClient(int socketDescriptor, MyServer *server);
~MyClient();
private:
QSslSocket* socket = NULL;
public slots:
void process();
}myclient.cpp:
void MyClient::process(){
//typical connection things
connect(this->socket, SIGNAL(encrypted()), this, SLOT(ready()));
}
void MyClient::ready(){
connect(socket,SIGNAL(readyRead()),this, SLOT(newData()));
}将在客户端线程中执行的DAO:
.cpp:
//DAO method
QList<QMap<QString, QString>> sqlResult = DatabaseService::executeQuery(sqlCommand);
//sqlResult processingDatabaseService:
.h:
class DatabaseService
{
public:
//...
static QMap<QString, QString> executeQuery(QString command);
private:
static QThreadStorage<QSqlDatabase> mDatabasePool;
static QSqlDatabase getDatabase();
};.cpp:
//...
QThreadStorage<QSqlDatabase> DatabaseService::mDatabasePool;
QSqlDatabase DatabaseService::getDatabase()
{
if(DatabaseService::mDatabasePool.hasLocalData()) {
return DatabaseService::mDatabasePool.localData();
} else {
auto database = QSqlDatabase::addDatabase("QPSQL", QUuid::createUuid().toString());
database.setHostName("hostName");
database.setDatabaseName("databaseName");
database.setUserName("user");
database.setPassword("password");
database.open();
DatabaseService::mDatabasePool.setLocalData(database);
return database;
}
}
QMap<QString,QString> DatabaseService::executeQuery(QString command){
QSqlQuery query (DatabaseService::getDatabase());
query.exec(command);
//...
return result;
}
//...这是所有与主题相关的代码。
您还可以检查我关于DB连接池的SO问题(请注意代码不完全相同)。
这个建筑有多好?什么是可以修正和改进的,以及如何改进?
发布于 2017-11-25 21:24:02
我不知道QThreads是如何工作的:
假设一个QThread是一个包装器,而不是池。
那么这个技术实际上是非常有限的。问题是线程的创建成本相对较高,实际上您可以同时运行其中的少数线程而不需要花费(创建超过2倍的处理器可能是个坏主意),在套接字编程中,大多数线程都是空闲的(网络比处理器的速度慢)。
在顶部的c10k上有一篇著名的论文。基本上,给定当前的网络速度和处理器速度,您应该能够很容易地支持10,000个同时连接。但是使用这个模型,您将支持几百个同时连接。
基本上,您希望围绕单个线程模型设计服务器,并使用pselect() (尽管现在更好的选项poll()、epoll()和最终LibEvent已经过时了)。不要费心尝试旧的版本,只需跳转到LibEvent。
https://codereview.stackexchange.com/questions/181303
复制相似问题