[SOLVED] Multithreaded QSslSocket Server Problem
-
Hey guys,
I have a problem regarding a multithreaded
QTcpServer
. Here is the server code:PDSSLServer::PDSSLServer(QWidget *parent) : QMainWindow(parent) { server = new QTcpServer(this); connect(server, SIGNAL(newConnection()), this, SLOT(newConnection())); connect(server, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(serverError(QAbstractSocket::SocketError))); } void PDSSLServer::newConnection() { qDebug() << "PDSSLServer::newConnection()"; while(server->hasPendingConnections()) { incomingConnection(server->nextPendingConnection()->socketDescriptor()); } } void PDSSLServer::incomingConnection(int socketDescriptor) { qDebug("PDSSLServer::incomingConnection(%d)", socketDescriptor); ClientThread *clThread = new ClientThread(socketDescriptor, SERVERCERTIFICATE_FILE); connect(clThread, SIGNAL(finished()), this, SLOT(threadClosed())); connect(clThread, SIGNAL(sqlError(QString)), this, SLOT(showSqlError(QString))); clThread->start(); }
I reduced the code due to readability. Here is the client code:
ClientThread::ClientThread(int socketDescr, QString serverCert, QObject *parent): QThread(parent) { qDebug() << "ClientThread::ClientThread(" <<socketDescr << "," << serverCert <<"," <<parent <<"):" <<parent; socketDescriptor = socketDescr; this->serverCert = serverCert; blockSize = 0; connect(this, SIGNAL(acceptSocket()), this, SLOT(createSocket())); emit acceptSocket(); } void ClientThread::run() { qDebug() << "ClientThread::run()"; exec(); } void ClientThread::createSocket() { //New Connection qDebug() << "New Thread with socket-ID: " << socketDescriptor; socket = new QSslSocket; if(!socket) { qWarning("not enough memory to create new QSslSocket!"); emit error(socket->error()); exit(1); } socket->setProtocol(QSsl::SslV3); connectSocketSignals(); socket->setSocketOption(QAbstractSocket::KeepAliveOption, true ); if(!socket->setSocketDescriptor(socketDescriptor)) { qWarning("could not set socket descriptor!"); socket->deleteLater(); exit(2); } startServerEncryption(); qDebug() << "Client connected" << socketDescriptor;
The reason why I emit the signal
acceptSocket()
in the constructor is that I have to communicate with the socket from another thread and therefore this thread has to be the owner of the socket which makes it impossible to create it in therun()
method.Here finally comes the problem which making me nuts. Everything is doing fine until I get to the point
if(!socket->setSocketDescriptor(socketDescriptor))
. I get an error message telling "QSocketNotifier: Multiple socket notifiers for same socket 748 and type Read". I know what it means but how can I resolve that issue? In my opinion its the correct way to set up a 'QSslSocket'. I've read a huge amount of posts here but nothing seems to work. Please help me out! -
Ok I finally sovled the issue. Sometimes it helps to read the documentation in detail...
In
QTcpServer
documentation for methodincomingConnection(qintptr socketDescriptor)
it says the following:"Note: If you want to handle an incoming connection as a new
QTcpSocket
object in another thread you have to pass thesocketDescriptor
to the other thread and create theQTcpSocket
object there and use itssetSocketDescriptor()
method."So what I simply had to do is the following:
#ifndef THREADEDTCPSERVER_H #define THREADEDTCPSERVER_H #include <QObject> #include <QTcpServer> class ThreadedTcpServer : public QTcpServer { Q_OBJECT public: ThreadedTcpServer(); ~ThreadedTcpServer(); signals: void newIncomingConnection(qintptr socketDescriptor); private: void incomingConnection(qintptr socketDescriptor); }; #endif // THREADEDTCPSERVER_H
#include "threadedtcpserver.h" ThreadedTcpServer::ThreadedTcpServer() { } ThreadedTcpServer::~ThreadedTcpServer() { } void ThreadedTcpServer::incomingConnection(qintptr socketDescriptor) { newIncomingConnection(socketDescriptor); }
Then connect the Signal
newIncomingConnection(socketDescriptor)
to thePDSSLServer::incomingConnection(int socketDescriptor)
method and it works! Maybe it helps somebody with the same issue. -
Hi,
since I am convinced that somebody else will also have similar problems I wrote a tutorial how to create a multithreaded server:
https://five-s.de/en/how-to-create-a-multithreaded-server-in-qt
Best regards