I'm creating a Qt TCP (with SSL) server to which multiple clients should connect and use the DB, and this is the main task. So, I think I can use this architecture: each client has its own thread, and clients use DB via DB connection pool.
Client connection part
main.cpp:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyServer server;
server.listen(QHostAddress::Any, 1234);
return a.exec();
}
myserver.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();
}
myclient.h:
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()));
}
DB connection pool part
DAO which will be executed in the client threads:
.cpp:
//DAO method
QList<QMap<QString, QString>> sqlResult = DatabaseService::executeQuery(sqlCommand);
//sqlResult processing
DatabaseService:
.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;
}
//...
This is all the code related to the subject.
You also can check my SO question about DB connection pool (please note that the code is not exactly the same).
So, how good is this architecture? What could be fixed and improved and how?