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. Reconnecting using QAbstractSocket::connectToHost
Forum Updated to NodeBB v4.3 + New Features

Reconnecting using QAbstractSocket::connectToHost

Scheduled Pinned Locked Moved Solved General and Desktop
14 Posts 2 Posters 39.4k Views
  • 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.
  • P pingal

    I'm facing a problem while reconnecting to the server. I've defined a class by the name Persistance_Connect whose purpose is to keep the connection alive. The constructor of the class contains:

    QObject::connect(&socket, &QAbstractSocket::disconnected, this, [](){qDebug() <<"Disconnected!";});
    QObject::connect(&socket, &QAbstractSocket::errorOccurred, this, &Persistance_Connect::onErr);
    

    After errorOccured, connectToHost() is called but the client doesn't reconnects to the server.

    void Persistance_Connect::onErr(QAbstractSocket::SocketError error)
    {
        qDebug() << "onErr is called";
        
        switch (error)
        {
        case QAbstractSocket::AddressInUseError:
            qDebug()<< "SOCKET ERROR: Address is already in use";
            break;
        case QAbstractSocket::ConnectionRefusedError:
            qDebug()<< "SOCKET ERROR: Connection refused";
            break;
        case QAbstractSocket::HostNotFoundError:
            qDebug()<< "SOCKET ERROR: Host not found";
            break;
        case QAbstractSocket::RemoteHostClosedError:
            qDebug()<< "SOCKET ERROR: Remote host closed";            
            break;  
        }
        
        socket.disconnectFromHost();
        qDebug() << "Trying to Reconnect to "<<Server_Addr<<":"<<Server_ConnectionPort;    
        socket.connectToHost(Server_Addr, Server_ConnectionPort, QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol);
    }
    

    The output is as follows after the server closes the connection

    Server_Addr:  "192.168.253.102"
    onErr is called
    SOCKET ERROR: Remote host closed
    Disconnected!
    Trying to Reconnect to  "192.168.253.102" : 7777
    

    After the above output, Client doesn't try to reconnect to the server.

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by
    #2

    @pingal said in Reconnecting using QAbstractSocket::connectToHost:

    socket.disconnectFromHost();
    qDebug() << "Trying to Reconnect to "<<Server_Addr<<":"<<Server_ConnectionPort;    
    socket.connectToHost(Server_Addr, Server_ConnectionPort, QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol);
    

    I would guess you are trying to reconnect (a) from within existing connect errorOccurred, which just might be problematic and (b) much too early after disconnectFromHost():

    Attempts to close the socket. If there is pending data waiting to be written, QAbstractSocket will enter ClosingState and wait until all data has been written. Eventually, it will enter UnconnectedState and emit the disconnected() signal.

    Try doing just the socket.disconnectFromHost(); here (assuming that is safe inside errorOccured, else do it on a timer). Do the reconnect when you have received the appropriate disconnected() signal?

    1 Reply Last reply
    0
    • P Offline
      P Offline
      pingal
      wrote on last edited by pingal
      #3

      Thanks for the reply,
      So now my connections are as following:

      QObject::connect(&socket, &QAbstractSocket::disconnected, this, &Persistance_Connect::onDisconnected);
      QObject::connect(&socket, &QAbstractSocket::errorOccurred, this, &Persistance_Connect::onErr);
      

      Here is the onErr:

      void Persistance_Connect::onErr(QAbstractSocket::SocketError error)
      {
          qDebug() << "onErr is called";
      
          switch (error)
          {
          case QAbstractSocket::AddressInUseError:
              qDebug()<< "SOCKET ERROR: Address is already in use";
              break;
          case QAbstractSocket::ConnectionRefusedError:
              qDebug()<< "SOCKET ERROR: Connection refused";
              break;
          case QAbstractSocket::HostNotFoundError:
              qDebug()<< "SOCKET ERROR: Host not found";
              break;
          case QAbstractSocket::RemoteHostClosedError:
              qDebug()<< "SOCKET ERROR: Remote host closed";
              break;
          }
      
          socket.disconnectFromHost();
      }
      

      And here is my disconnect handler

      void Persistance_Connect::onDisconnected()
      {
          qDebug() << "Disconnected! Trying to Reconnect to "<<Server_Addr<<":"<<Server_ConnectionPort;
          socket.connectToHost(Server_Addr, Server_ConnectionPort, QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol);
      }
      

      Still it doesn't reconnect. Here is the output when i tried to close connection from server after a succesfull connect

      Connected!
      Server_Addr:  "192.168.253.102"
      onErr is called
      SOCKET ERROR: Remote host closed
      Disconnected! Trying to Reconnect to  "192.168.253.102" : 7777
      
      JonBJ 1 Reply Last reply
      0
      • P pingal

        Thanks for the reply,
        So now my connections are as following:

        QObject::connect(&socket, &QAbstractSocket::disconnected, this, &Persistance_Connect::onDisconnected);
        QObject::connect(&socket, &QAbstractSocket::errorOccurred, this, &Persistance_Connect::onErr);
        

        Here is the onErr:

        void Persistance_Connect::onErr(QAbstractSocket::SocketError error)
        {
            qDebug() << "onErr is called";
        
            switch (error)
            {
            case QAbstractSocket::AddressInUseError:
                qDebug()<< "SOCKET ERROR: Address is already in use";
                break;
            case QAbstractSocket::ConnectionRefusedError:
                qDebug()<< "SOCKET ERROR: Connection refused";
                break;
            case QAbstractSocket::HostNotFoundError:
                qDebug()<< "SOCKET ERROR: Host not found";
                break;
            case QAbstractSocket::RemoteHostClosedError:
                qDebug()<< "SOCKET ERROR: Remote host closed";
                break;
            }
        
            socket.disconnectFromHost();
        }
        

        And here is my disconnect handler

        void Persistance_Connect::onDisconnected()
        {
            qDebug() << "Disconnected! Trying to Reconnect to "<<Server_Addr<<":"<<Server_ConnectionPort;
            socket.connectToHost(Server_Addr, Server_ConnectionPort, QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol);
        }
        

        Still it doesn't reconnect. Here is the output when i tried to close connection from server after a succesfull connect

        Connected!
        Server_Addr:  "192.168.253.102"
        onErr is called
        SOCKET ERROR: Remote host closed
        Disconnected! Trying to Reconnect to  "192.168.253.102" : 7777
        
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #4

        @pingal

        • How do we know for sure that whatever the server is it accepts reconnections? After the disconnectFromHost() in this application, try running e.g. a new instance of this application and verify that can connect first time?

        • Put a slot on void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState) and monitor how the state is changing.

        • Not sure if it's relevant but try putting the disconnectFromHost() and/or the connectToHost() on a QTimer::singleShot() so that they do not happen while still inside a slot on the old connection, in case that makes any difference?

        • Temporarily try using a second, distinct QAbstractSocket socket2 (persistent, same place as wherever your current socket is declared) for the re-connect, just in case there is an issue on re-connecting the existing one?

        P 1 Reply Last reply
        0
        • JonBJ JonB

          @pingal

          • How do we know for sure that whatever the server is it accepts reconnections? After the disconnectFromHost() in this application, try running e.g. a new instance of this application and verify that can connect first time?

          • Put a slot on void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState) and monitor how the state is changing.

          • Not sure if it's relevant but try putting the disconnectFromHost() and/or the connectToHost() on a QTimer::singleShot() so that they do not happen while still inside a slot on the old connection, in case that makes any difference?

          • Temporarily try using a second, distinct QAbstractSocket socket2 (persistent, same place as wherever your current socket is declared) for the re-connect, just in case there is an issue on re-connecting the existing one?

          P Offline
          P Offline
          pingal
          wrote on last edited by
          #5
          • How do we know for sure that whatever the server is it accepts reconnections? After the disconnectFromHost() in this application, try running e.g. a new instance of this application and verify that can connect first time?

          Yes, the server accepts reconnection and i've tried that using another instance.

          • Put a slot on void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState) and monitor how the state is changing.

          Here is the output when the client is connected to the server

          QAbstractSocket::HostLookupState
          QAbstractSocket::ConnectingState
          QAbstractSocket::ConnectedState
          Connected!
          Server_Addr:  "192.168.253.102"
          

          And when the server closes the connection

          onErr is called
          SOCKET ERROR: Remote host closed
          QAbstractSocket::ClosingState
          QAbstractSocket::UnconnectedState
          Disconnected! Trying to Reconnect to  "192.168.253.102" : 7777
          QAbstractSocket::HostLookupState
          QAbstractSocket::ConnectingState
          
          • Not sure if it's relevant but try putting the disconnectFromHost() and/or the connectToHost() on a QTimer::singleShot() so that they do not happen while still inside a slot on the old connection, in case that makes any difference?

          Have not tried it yet

          • Temporarily try using a second, distinct QAbstractSocket socket2 (persistent, same place as wherever your current socket is declared) for the re-connect, just in case there is an issue on re-connecting the existing one?

          Have not tried it yet

          JonBJ 2 Replies Last reply
          0
          • P pingal
            • How do we know for sure that whatever the server is it accepts reconnections? After the disconnectFromHost() in this application, try running e.g. a new instance of this application and verify that can connect first time?

            Yes, the server accepts reconnection and i've tried that using another instance.

            • Put a slot on void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState) and monitor how the state is changing.

            Here is the output when the client is connected to the server

            QAbstractSocket::HostLookupState
            QAbstractSocket::ConnectingState
            QAbstractSocket::ConnectedState
            Connected!
            Server_Addr:  "192.168.253.102"
            

            And when the server closes the connection

            onErr is called
            SOCKET ERROR: Remote host closed
            QAbstractSocket::ClosingState
            QAbstractSocket::UnconnectedState
            Disconnected! Trying to Reconnect to  "192.168.253.102" : 7777
            QAbstractSocket::HostLookupState
            QAbstractSocket::ConnectingState
            
            • Not sure if it's relevant but try putting the disconnectFromHost() and/or the connectToHost() on a QTimer::singleShot() so that they do not happen while still inside a slot on the old connection, in case that makes any difference?

            Have not tried it yet

            • Temporarily try using a second, distinct QAbstractSocket socket2 (persistent, same place as wherever your current socket is declared) for the re-connect, just in case there is an issue on re-connecting the existing one?

            Have not tried it yet

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #6

            @pingal said in Reconnecting using QAbstractSocket::connectToHost:

            QAbstractSocket::ConnectingState

            Looks to me like the client side is doing its bit but the server side is not accepting the reconnection, in a timely fashion. Do try those last 2 suggestions, especially the second one.

            Are you in charge of (have the code to) the server side, or is that third-party?

            P 1 Reply Last reply
            0
            • P pingal
              • How do we know for sure that whatever the server is it accepts reconnections? After the disconnectFromHost() in this application, try running e.g. a new instance of this application and verify that can connect first time?

              Yes, the server accepts reconnection and i've tried that using another instance.

              • Put a slot on void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState) and monitor how the state is changing.

              Here is the output when the client is connected to the server

              QAbstractSocket::HostLookupState
              QAbstractSocket::ConnectingState
              QAbstractSocket::ConnectedState
              Connected!
              Server_Addr:  "192.168.253.102"
              

              And when the server closes the connection

              onErr is called
              SOCKET ERROR: Remote host closed
              QAbstractSocket::ClosingState
              QAbstractSocket::UnconnectedState
              Disconnected! Trying to Reconnect to  "192.168.253.102" : 7777
              QAbstractSocket::HostLookupState
              QAbstractSocket::ConnectingState
              
              • Not sure if it's relevant but try putting the disconnectFromHost() and/or the connectToHost() on a QTimer::singleShot() so that they do not happen while still inside a slot on the old connection, in case that makes any difference?

              Have not tried it yet

              • Temporarily try using a second, distinct QAbstractSocket socket2 (persistent, same place as wherever your current socket is declared) for the re-connect, just in case there is an issue on re-connecting the existing one?

              Have not tried it yet

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #7

              @pingal
              UPDATE
              Especially if you do find that a new socket2 does work: on your existing socket try calling bool QIODevice::reset() after disconnect before reconnect.

              And/or, read https://bugreports.qt.io/browse/QTBUG-18082?focusedCommentId=170619&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-170619, which seems to me to be your issue, re: my suggestion that after error there might be a problem. That is claiming

              The issue here is that connectToHost() is being called from within a slot connected to error() and that doesn't work, making ComEngine::connectToHost() into a slot and using QMetaObject::invokeMethod(this, "connectToHost", Qt::QueuedConnection); to have the reconnection attempt be made after works like a charm.

              "Bug" is over 10 years ago, but that doesn't stop it possibly still be applicable in QT... :) Read through https://stackoverflow.com/questions/11600288/qtcpsocket-client-auto-reconnect too.

              1 Reply Last reply
              0
              • JonBJ JonB

                @pingal said in Reconnecting using QAbstractSocket::connectToHost:

                QAbstractSocket::ConnectingState

                Looks to me like the client side is doing its bit but the server side is not accepting the reconnection, in a timely fashion. Do try those last 2 suggestions, especially the second one.

                Are you in charge of (have the code to) the server side, or is that third-party?

                P Offline
                P Offline
                pingal
                wrote on last edited by
                #8

                Looks to me like the client side is doing its bit but the server side is not accepting the reconnection

                I'm using a simple server i.e. netcat for debugging purposes and it works fine, I've even checked the signals from client to server in wireshark to verify that the client indeed is not requesting connection after disconnect, contrary to the QAbstractSocket::ConnectingState

                Untitled.png

                JonBJ 1 Reply Last reply
                0
                • P pingal

                  Looks to me like the client side is doing its bit but the server side is not accepting the reconnection

                  I'm using a simple server i.e. netcat for debugging purposes and it works fine, I've even checked the signals from client to server in wireshark to verify that the client indeed is not requesting connection after disconnect, contrary to the QAbstractSocket::ConnectingState

                  Untitled.png

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #9

                  @pingal
                  Point taken. Try the suggestions I have posted in previous 2 posts.

                  Also i have just spotted what I thought in the docs for errorOccurred():

                  When this signal is emitted, the socket may not be ready for a reconnect attempt. In that case, attempts to reconnect should be done from the event loop. For example, use a QTimer::singleShot() with 0 as the timeout.

                  P 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @pingal
                    Point taken. Try the suggestions I have posted in previous 2 posts.

                    Also i have just spotted what I thought in the docs for errorOccurred():

                    When this signal is emitted, the socket may not be ready for a reconnect attempt. In that case, attempts to reconnect should be done from the event loop. For example, use a QTimer::singleShot() with 0 as the timeout.

                    P Offline
                    P Offline
                    pingal
                    wrote on last edited by
                    #10

                    @JonB said in Reconnecting using QAbstractSocket::connectToHost:

                    @pingal
                    Point taken. Try the suggestions I have posted in previous 2 posts.

                    Also i have just spotted what I thought in the docs for errorOccurred():

                    When this signal is emitted, the socket may not be ready for a reconnect attempt. In that case, attempts to reconnect should be done from the event loop. For example, use a QTimer::singleShot() with 0 as the timeout.

                    using QTimer::singleShot like below:

                    void Persistance_Connect::onDisconnected()
                    {
                        qDebug() << "Disconnected! Trying to Reconnect to "<<Server_Addr<<":"<<Server_ConnectionPort;
                       QTimer::singleShot(0, this, SLOT(connect("192.168.253.102", 7777)));
                        socket.connectToHost(Server_Addr, Server_ConnectionPort, QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol);
                    }
                    

                    output:

                    QMetaObject::invokeMethod: No such method Persistance_Connect::connect()
                    

                    I think I'm doing it wrong, kindly ignore my ignorance.

                    I've created socket2 for reconnection phase, same results.

                    JonBJ 1 Reply Last reply
                    0
                    • P pingal

                      @JonB said in Reconnecting using QAbstractSocket::connectToHost:

                      @pingal
                      Point taken. Try the suggestions I have posted in previous 2 posts.

                      Also i have just spotted what I thought in the docs for errorOccurred():

                      When this signal is emitted, the socket may not be ready for a reconnect attempt. In that case, attempts to reconnect should be done from the event loop. For example, use a QTimer::singleShot() with 0 as the timeout.

                      using QTimer::singleShot like below:

                      void Persistance_Connect::onDisconnected()
                      {
                          qDebug() << "Disconnected! Trying to Reconnect to "<<Server_Addr<<":"<<Server_ConnectionPort;
                         QTimer::singleShot(0, this, SLOT(connect("192.168.253.102", 7777)));
                          socket.connectToHost(Server_Addr, Server_ConnectionPort, QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol);
                      }
                      

                      output:

                      QMetaObject::invokeMethod: No such method Persistance_Connect::connect()
                      

                      I think I'm doing it wrong, kindly ignore my ignorance.

                      I've created socket2 for reconnection phase, same results.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #11

                      @pingal said in Reconnecting using QAbstractSocket::connectToHost:

                      I've created socket2 for reconnection phase, same results.

                      That stumps me. If you can re-connect from a separate program but not from a brand new socket in the same program I don't know what to tell you. You can see from those links other people claimed to get it working.

                      The code you tried might better be, say:

                      // declare this method after `public slots:` in `.h` file
                      void Persistance_Connect::reconnect()
                      {
                          socket.connectToHost(Server_Addr, Server_ConnectionPort, QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol);
                      }
                      
                      void Persistance_Connect::onDisconnected()
                      {
                          qDebug() << "Disconnected! Trying to Reconnect to "<<Server_Addr<<":"<<Server_ConnectionPort;
                          QTimer::singleShot(0, this, &Persistance_Connect::reconnect);
                      }
                      

                      but frankly if you cannot even get a fresh socket to reconnect I have little hope....

                      P 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @pingal said in Reconnecting using QAbstractSocket::connectToHost:

                        I've created socket2 for reconnection phase, same results.

                        That stumps me. If you can re-connect from a separate program but not from a brand new socket in the same program I don't know what to tell you. You can see from those links other people claimed to get it working.

                        The code you tried might better be, say:

                        // declare this method after `public slots:` in `.h` file
                        void Persistance_Connect::reconnect()
                        {
                            socket.connectToHost(Server_Addr, Server_ConnectionPort, QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol);
                        }
                        
                        void Persistance_Connect::onDisconnected()
                        {
                            qDebug() << "Disconnected! Trying to Reconnect to "<<Server_Addr<<":"<<Server_ConnectionPort;
                            QTimer::singleShot(0, this, &Persistance_Connect::reconnect);
                        }
                        

                        but frankly if you cannot even get a fresh socket to reconnect I have little hope....

                        P Offline
                        P Offline
                        pingal
                        wrote on last edited by
                        #12
                        This post is deleted!
                        1 Reply Last reply
                        0
                        • P Offline
                          P Offline
                          pingal
                          wrote on last edited by pingal
                          #13

                          So now i placed the reconnect in onErr like below

                          void Persistance_Connect::onErr(QAbstractSocket::SocketError error)
                          {
                              switch (error)
                              {
                              case QAbstractSocket::AddressInUseError:
                                  qDebug()<< "SOCKET ERROR: Address is already in use";
                                  break;
                              case QAbstractSocket::ConnectionRefusedError:
                                  qDebug()<< "SOCKET ERROR: Connection refused";
                                  break;
                              case QAbstractSocket::HostNotFoundError:
                                  qDebug()<< "SOCKET ERROR: Host not found";
                                  break;
                              case QAbstractSocket::RemoteHostClosedError:
                                  qDebug()<< "SOCKET ERROR: Remote host closed";
                                  break;
                              }
                              socket.disconnectFromHost();
                              QTimer::singleShot(0, this, &Persistance_Connect::reconnect); // Added here
                          }
                          

                          And removed the above from onDisconnect(). The module works fine now.

                          @JonB Thank you very much :)))

                          JonBJ 1 Reply Last reply
                          2
                          • P pingal

                            So now i placed the reconnect in onErr like below

                            void Persistance_Connect::onErr(QAbstractSocket::SocketError error)
                            {
                                switch (error)
                                {
                                case QAbstractSocket::AddressInUseError:
                                    qDebug()<< "SOCKET ERROR: Address is already in use";
                                    break;
                                case QAbstractSocket::ConnectionRefusedError:
                                    qDebug()<< "SOCKET ERROR: Connection refused";
                                    break;
                                case QAbstractSocket::HostNotFoundError:
                                    qDebug()<< "SOCKET ERROR: Host not found";
                                    break;
                                case QAbstractSocket::RemoteHostClosedError:
                                    qDebug()<< "SOCKET ERROR: Remote host closed";
                                    break;
                                }
                                socket.disconnectFromHost();
                                QTimer::singleShot(0, this, &Persistance_Connect::reconnect); // Added here
                            }
                            

                            And removed the above from onDisconnect(). The module works fine now.

                            @JonB Thank you very much :)))

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by JonB
                            #14

                            @pingal said in Reconnecting using QAbstractSocket::connectToHost:

                            The module works fine now.

                            Wow, that's great! (Still don't know why a socket2 did not work, but never mind.)

                            Like I suspected/wondered, the stackoverflow answers said that there is still some "clear up" which needs to be done after the disconnectFromHost() before a new connectToHost() will work on the socket, and that clear up needs to take place (somewhere/how) in the main event loop. Using a QTimer to delay, even with just a delay of 0, allows the main event loop to be re-entered to do its magic before it executes the reconnect.

                            BTW, note how I (always) use New Signal Slot Syntax for my connect()s, never the old style SIGNAL/SLOT() macros. This was actually introduced a long time ago at Qt5, but sadly many/most web examples still use the old syntax. The new one is much cleaner, and will pick up at compile-time whether the slot correctly matches the signal, instead of it failing (obscurely) at run-time. I suggest you always use the new style.

                            1 Reply Last reply
                            2

                            • Login

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