Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    [SOLVED] Multithreaded QSslSocket Server Problem

    General and Desktop
    qsslsocket qtcpserver qtcpsocket qthread qssl ssl qsocketnotifier
    1
    3
    2684
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      SebastianS last edited by SebastianS

      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!

      1 Reply Last reply Reply Quote 0
      • S
        SebastianS last edited by

        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.

        1 Reply Last reply Reply Quote 0
        • S
          SebastianS last edited by

          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

          1 Reply Last reply Reply Quote 0
          • First post
            Last post