[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 the run() 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 method incomingConnection(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 the socketDescriptor to the other thread and create the QTcpSocket object there and use its setSocketDescriptor() 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 the PDSSLServer::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



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.