Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QTcpServer / QTcpSocket help
Qt 6.11 is out! See what's new in the release blog

QTcpServer / QTcpSocket help

Scheduled Pinned Locked Moved Unsolved General and Desktop
17 Posts 5 Posters 1.6k Views 1 Watching
  • 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.
  • jsulmJ jsulm

    @SPlatten Did you make sure incomingConnection was called?

    SPlattenS Offline
    SPlattenS Offline
    SPlatten
    wrote on last edited by
    #4

    @jsulm I can see incomingConnection is called as I have a breakpoint in the function on the last line.

    1 Reply Last reply
    0
    • KroMignonK KroMignon

      @SPlatten said in QTcpServer / QTcpSocket help:

      First, this is not a good practice:

      Q_ASSERT_X(listen(QHostAddress::Any, clsSocketServer::mscuint16port)!=false
      ,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());

      When build as release, this will be removed!
      Please change this into:

      bool success = listen(QHostAddress::Any, clsSocketServer::mscuint16port);
      Q_ASSERT_X(!success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
      

      or

      listen(QHostAddress::Any, clsSocketServer::mscuint16port);
      Q_ASSERT_X(!isListening(),"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
      
      SPlattenS Offline
      SPlattenS Offline
      SPlatten
      wrote on last edited by
      #5

      @KroMignon Thank you, good call!

      1 Reply Last reply
      0
      • SPlattenS SPlatten

        I'm writing and application that uses QTcpServer and another that uses QTcpSocket. The server application inherits from QTcpServer:

        class clsSocketServer : public QTcpServer {
        Q_OBJECT
        
        protected:
            void incomingConnection(qintptr sfd);
        
        public:
            static const QString mscstrCRLF;
            static const quint16 mscuint16port;
        
            explicit clsSocketServer(QObject* pParent = nullptr);
            ~clsSocketServer();
        
        public slots:
            void discardClient();
            void readClient();
        };
        

        Implementation:

        const QString clsSocketServer::mscstrCRLF("\r\n");
        const quint16 clsSocketServer::mscuint16port = 8123;
        /**
         * @brief clsSocketServer::clsSocketServer - class constructor
         */
        clsSocketServer::clsSocketServer(QObject* pParent) : QTcpServer(pParent) {
            QString strListenFailure = QString("Cannot listen to port: ") + QString::number(clsSocketServer::mscuint16port);
            Q_ASSERT_X(listen(QHostAddress::Any, clsSocketServer::mscuint16port)!=false
                      ,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
        }
        /**
         * @brief clsSocketServer::~clsSocketServer - class destructor
         */
        clsSocketServer::~clsSocketServer() {
            close();
        }
        /**
         * @brief clsSocketServer::discardClient
         */
        void clsSocketServer::discardClient() {
            QTcpSocket* pSckClient = (QTcpSocket*)sender();
            pSckClient->deleteLater();
        }
        /**
         * @brief clsSocketService::incomingConnection
         * @param sfd : Client Socket Descriptor
         */
        void clsSocketServer::incomingConnection(qintptr sfd) {
            QTcpSocket* pSckClient = new QTcpSocket(this);    
            connect(pSckClient, SIGNAL(readyRead()), this, SLOT(readClient()));
            connect(pSckClient, SIGNAL(disconnected()), this, SLOT(discardClient()));
            pSckClient->setSocketDescriptor(sfd);
        }
        /**
         * @brief clsSocketServer::readClient
         */
        void clsSocketServer::readClient() {
            enum {
                REQ_METHOD = 0
               ,REQ_DATA
            };
            QTcpSocket* pSckClient = (QTcpSocket*)sender();
        
            if (!pSckClient->canReadLine() ) {
            //Cannot read input stream, abort!
                return;
            }
            QStringList slstTokens = QString(pSckClient->readLine()).split(QRegExp("[ \r\n][ \r\n]*"));
           ...
        }
        

        My application launches a child process which uses QTcpSocket:

        //Set-up the data stream
        mdsIn.setDevice(this);
        mdsIn.setVersion(QDataStream::Qt_5_15);
        //Connect up the signals
        connect(this, &QIODevice::readyRead, this, &clsModHelper::dataIn);
        connect(this, &QAbstractSocket::errorOccurred, this, &clsModHelper::errorOccurred);
        //Connect to the Application
        connectToHost(clsModHelper::mscpszHost, muint16Port);
        
        if ( !waitForConnected(clsModHelper::mscintConnectionTimeout) ) {
            exit(EXIT_FAILURE);
        }    
        

        clsModHelper::mscpszHost is "localhost" and muint16Port is 8123. The slots for dataIn and errorOccurred:

        /**
         * @brief clsModHelper::dataIn
         */
        void clsModHelper::dataIn() {
            qdbg() << "dataIn";
        }
        /**
         * @brief clsModHelper::errorOccurred
         * @param socketError : Error information
         */
        void clsModHelper::errorOccurred(QAbstractSocket::SocketError socketError) {
            qdbg() << "errorOccurred: " << errorString();
        }
        

        I'm not seeing anything in either dataIn or errorOccurred. I also tried adding:

        pSckClient->write("Hello", 5);
        

        To the end of the incomingConnection function in the main application, I don't see it received by the child process. What have I done wrong or missed out?

        KroMignonK Offline
        KroMignonK Offline
        KroMignon
        wrote on last edited by
        #6

        @SPlatten And second, where did you connect QTcpServer::newConnection?

        I am missing something like:

        clsSocketServer::clsSocketServer(QObject* pParent) : QTcpServer(pParent) {
            connect(this, &QTcpServer::newConnection, [this](){
                while(hasPendingConnections())
                {
                    auto socket = m_server->nextPendingConnection();
                    if(!socket)
                        break;
                    // do something with the client!
                }
        
            });
            bool success = listen(QHostAddress::Any, clsSocketServer::mscuint16port);
            Q_ASSERT_X(!success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
        }
        

        It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

        SPlattenS Christian EhrlicherC 2 Replies Last reply
        0
        • KroMignonK KroMignon

          @SPlatten And second, where did you connect QTcpServer::newConnection?

          I am missing something like:

          clsSocketServer::clsSocketServer(QObject* pParent) : QTcpServer(pParent) {
              connect(this, &QTcpServer::newConnection, [this](){
                  while(hasPendingConnections())
                  {
                      auto socket = m_server->nextPendingConnection();
                      if(!socket)
                          break;
                      // do something with the client!
                  }
          
              });
              bool success = listen(QHostAddress::Any, clsSocketServer::mscuint16port);
              Q_ASSERT_X(!success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
          }
          
          SPlattenS Offline
          SPlattenS Offline
          SPlatten
          wrote on last edited by
          #7

          @KroMignon, I used:
          https://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html

          As a guide for the server, I don't see anything like that on that page?

          1 Reply Last reply
          0
          • KroMignonK KroMignon

            @SPlatten And second, where did you connect QTcpServer::newConnection?

            I am missing something like:

            clsSocketServer::clsSocketServer(QObject* pParent) : QTcpServer(pParent) {
                connect(this, &QTcpServer::newConnection, [this](){
                    while(hasPendingConnections())
                    {
                        auto socket = m_server->nextPendingConnection();
                        if(!socket)
                            break;
                        // do something with the client!
                    }
            
                });
                bool success = listen(QHostAddress::Any, clsSocketServer::mscuint16port);
                Q_ASSERT_X(!success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
            }
            
            Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #8

            @KroMignon said in QTcpServer / QTcpSocket help:

            And second, where did you connect QTcpServer::newConnection?

            He's overwriting QTcpServer::incomingConnection() because he follows the threading example (for unknown reasons)

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            SPlattenS 1 Reply Last reply
            0
            • KroMignonK KroMignon

              @SPlatten said in QTcpServer / QTcpSocket help:

              First, this is not a good practice:

              Q_ASSERT_X(listen(QHostAddress::Any, clsSocketServer::mscuint16port)!=false
              ,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());

              When build as release, this will be removed!
              Please change this into:

              bool success = listen(QHostAddress::Any, clsSocketServer::mscuint16port);
              Q_ASSERT_X(!success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
              

              or

              listen(QHostAddress::Any, clsSocketServer::mscuint16port);
              Q_ASSERT_X(!isListening(),"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
              
              SPlattenS Offline
              SPlattenS Offline
              SPlatten
              wrote on last edited by
              #9

              @KroMignon, Are you sure your test in Q_ASSERT_X is correct? I get an exception immediately when using !isListening() or !success.

              KroMignonK 1 Reply Last reply
              0
              • Christian EhrlicherC Christian Ehrlicher

                @KroMignon said in QTcpServer / QTcpSocket help:

                And second, where did you connect QTcpServer::newConnection?

                He's overwriting QTcpServer::incomingConnection() because he follows the threading example (for unknown reasons)

                SPlattenS Offline
                SPlattenS Offline
                SPlatten
                wrote on last edited by
                #10

                @Christian-Ehrlicher , is it wrong?

                KroMignonK 1 Reply Last reply
                0
                • SPlattenS SPlatten

                  @KroMignon, Are you sure your test in Q_ASSERT_X is correct? I get an exception immediately when using !isListening() or !success.

                  KroMignonK Offline
                  KroMignonK Offline
                  KroMignon
                  wrote on last edited by
                  #11

                  @SPlatten said in QTcpServer / QTcpSocket help:

                  Are you sure your test in Q_ASSERT_X is correct?

                  my bad, sorry: the test is inverted!
                  should be

                  Q_ASSERT_X(success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
                  or 
                  Q_ASSERT_X(isListening(),"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
                  

                  It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                  SPlattenS 1 Reply Last reply
                  2
                  • KroMignonK KroMignon

                    @SPlatten said in QTcpServer / QTcpSocket help:

                    Are you sure your test in Q_ASSERT_X is correct?

                    my bad, sorry: the test is inverted!
                    should be

                    Q_ASSERT_X(success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
                    or 
                    Q_ASSERT_X(isListening(),"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
                    
                    SPlattenS Offline
                    SPlattenS Offline
                    SPlatten
                    wrote on last edited by
                    #12

                    @KroMignon , Thanks for confirming.

                    1 Reply Last reply
                    0
                    • SPlattenS SPlatten

                      @Christian-Ehrlicher , is it wrong?

                      KroMignonK Offline
                      KroMignonK Offline
                      KroMignon
                      wrote on last edited by KroMignon
                      #13

                      @SPlatten said in QTcpServer / QTcpSocket help:

                      is it wrong?

                      It is not specially wrong, but using QTcpServer::waitForConnected() is a blocking method, so no event will be handled during this call for the used thread!

                      Using QTcpServer::newConnection() signal is the non blocking alternative, which is more QEventLoop/QEvent friendly ;)

                      ==> Read documentation for more details

                      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                      SPlattenS 1 Reply Last reply
                      3
                      • KroMignonK KroMignon

                        @SPlatten said in QTcpServer / QTcpSocket help:

                        is it wrong?

                        It is not specially wrong, but using QTcpServer::waitForConnected() is a blocking method, so no event will be handled during this call for the used thread!

                        Using QTcpServer::newConnection() signal is the non blocking alternative, which is more QEventLoop/QEvent friendly ;)

                        ==> Read documentation for more details

                        SPlattenS Offline
                        SPlattenS Offline
                        SPlatten
                        wrote on last edited by SPlatten
                        #14

                        @KroMignon, I call connectToHost in the process that is launched this connects to the application that launched it and this uses QTcpSocket not QTcpServer. The new connection would be created by the launcher when it processes the connection.

                        I call waitForConnection purposely as the child process has no other purpose without a connection to the launcher.

                        I think the problem is in the launcher in this function:

                        void clsSocketServer::incomingConnection(qintptr sfd) {
                            QTcpSocket* pSckClient = new QTcpSocket(this);    
                            connect(pSckClient, SIGNAL(readyRead()), this, SLOT(readClient()));
                            connect(pSckClient, SIGNAL(disconnected()), this, SLOT(discardClient()));
                            pSckClient->setSocketDescriptor(sfd);
                        
                            pSckClient->write("Hello", 5);
                        }
                        

                        I can see in the debugger an incomingConnection is called, but the test write, doesn't happen.

                        1 Reply Last reply
                        0
                        • KroMignonK KroMignon

                          @SPlatten said in QTcpServer / QTcpSocket help:

                          First, this is not a good practice:

                          Q_ASSERT_X(listen(QHostAddress::Any, clsSocketServer::mscuint16port)!=false
                          ,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());

                          When build as release, this will be removed!
                          Please change this into:

                          bool success = listen(QHostAddress::Any, clsSocketServer::mscuint16port);
                          Q_ASSERT_X(!success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
                          

                          or

                          listen(QHostAddress::Any, clsSocketServer::mscuint16port);
                          Q_ASSERT_X(!isListening(),"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());
                          
                          VRoninV Offline
                          VRoninV Offline
                          VRonin
                          wrote on last edited by
                          #15

                          @KroMignon said in QTcpServer / QTcpSocket help:

                          Please change this into:
                          bool success = listen(QHostAddress::Any, clsSocketServer::mscuint16port);
                          Q_ASSERT_X(!success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());

                          or
                          listen(QHostAddress::Any, clsSocketServer::mscuint16port);
                          Q_ASSERT_X(!isListening(),"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());

                          You can use Q_ASSUME is for this kind of cases. Q_ASSUME(listen(QHostAddress::Any, clsSocketServer::mscuint16port));

                          @SPlatten said in QTcpServer / QTcpSocket help:

                          I used:
                          https://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html

                          Unfortunately that's not a good example to start on TCP. Some of us here prepared a better example to serve as a starting point, have a look at https://wiki.qt.io/WIP-How_to_create_a_simple_chat_application

                          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                          ~Napoleon Bonaparte

                          On a crusade to banish setIndexWidget() from the holy land of Qt

                          SPlattenS 2 Replies Last reply
                          5
                          • VRoninV VRonin

                            @KroMignon said in QTcpServer / QTcpSocket help:

                            Please change this into:
                            bool success = listen(QHostAddress::Any, clsSocketServer::mscuint16port);
                            Q_ASSERT_X(!success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());

                            or
                            listen(QHostAddress::Any, clsSocketServer::mscuint16port);
                            Q_ASSERT_X(!isListening(),"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());

                            You can use Q_ASSUME is for this kind of cases. Q_ASSUME(listen(QHostAddress::Any, clsSocketServer::mscuint16port));

                            @SPlatten said in QTcpServer / QTcpSocket help:

                            I used:
                            https://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html

                            Unfortunately that's not a good example to start on TCP. Some of us here prepared a better example to serve as a starting point, have a look at https://wiki.qt.io/WIP-How_to_create_a_simple_chat_application

                            SPlattenS Offline
                            SPlattenS Offline
                            SPlatten
                            wrote on last edited by
                            #16

                            @VRonin , thank you, I will take a look now.

                            1 Reply Last reply
                            0
                            • VRoninV VRonin

                              @KroMignon said in QTcpServer / QTcpSocket help:

                              Please change this into:
                              bool success = listen(QHostAddress::Any, clsSocketServer::mscuint16port);
                              Q_ASSERT_X(!success,"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());

                              or
                              listen(QHostAddress::Any, clsSocketServer::mscuint16port);
                              Q_ASSERT_X(!isListening(),"clsSocketServer::clsSocketServer", strListenFailure.toLatin1().data());

                              You can use Q_ASSUME is for this kind of cases. Q_ASSUME(listen(QHostAddress::Any, clsSocketServer::mscuint16port));

                              @SPlatten said in QTcpServer / QTcpSocket help:

                              I used:
                              https://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html

                              Unfortunately that's not a good example to start on TCP. Some of us here prepared a better example to serve as a starting point, have a look at https://wiki.qt.io/WIP-How_to_create_a_simple_chat_application

                              SPlattenS Offline
                              SPlattenS Offline
                              SPlatten
                              wrote on last edited by
                              #17
                              This post is deleted!
                              1 Reply Last reply
                              0

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved