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. QTcpSocket state always connected

QTcpSocket state always connected

Scheduled Pinned Locked Moved Unsolved General and Desktop
qtcpsocketclient
23 Posts 7 Posters 17.2k 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.
  • Gianluca86G Gianluca86

    It prints the disconnection message. But the state doesn't change.
    I think I'll give up, I'll use the Send and Receive timeout to check the connection. Thanks for the help.

    raven-worxR Offline
    raven-worxR Offline
    raven-worx
    Moderators
    wrote on last edited by
    #14

    @Gianluca86 said in QTcpSocket state always connected:

    It prints the disconnection message. But the state doesn't change.

    Since you said you do not need to post more code, i tell you it's impossible to achieve what you want with the code you've posted so far.
    I also do not know how you are checking the state. Obviously the code you've posted only checks the state once. And thats right after a connection happened...

    So what do you actually expect?

    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
    If you have a question please use the forum so others can benefit from the solution in the future

    1 Reply Last reply
    2
    • Gianluca86G Offline
      Gianluca86G Offline
      Gianluca86
      wrote on last edited by
      #15

      After the connection, I call the function with the check state every 3 seconds, with a timer.
      I don't do anything special, I simply create a Socket, connect and check state, nothing more.
      So I would expect that if the server program to which I was connected closes, the state of my tcpsocket changes, but unfortunately it doesn't happen, so I'll have to use another method to know if the connection is active.

      thanks anyway

      1 Reply Last reply
      0
      • Gianluca86G Gianluca86

        It prints the disconnection message. But the state doesn't change.
        I think I'll give up, I'll use the Send and Receive timeout to check the connection. Thanks for the help.

        VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by
        #16

        @Gianluca86 said in QTcpSocket state always connected:

        But the state doesn't change.

        Pretty sure it does https://code.woboq.org/qt5/qtbase/src/network/socket/qabstractsocket.cpp.html#2788

        In fact you can connect to stateChanged signal to check that

        "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

        1 Reply Last reply
        0
        • puzzled_giraffeP Offline
          puzzled_giraffeP Offline
          puzzled_giraffe
          wrote on last edited by puzzled_giraffe
          #17

          Hi everyone.
          Topic is old, but problem still exists. I'm using QT 5.14.1 on Windows 7 and tried to compile project with MinGW(32/64) and MSVC17(32/64), but results are same: socket does not react on physical disconnect.
          It is important remark that I can't use blocking calls (like waitForBytesWritten() / waitForConnected() / etc) in my project.

          First I used next check (I think TS talked about something like this):

          bool IsConnected() {
               return socket_.state() == QTcpSocket::ConnectedState;
          }
          //---- somewhere in code -----
          if(IsConnected()) {
             // do something;
          } else { /*error occured*/ }
          

          And I got same result: if wire was plugged out after connection state still was ::ConnectedState. Next I tried to use socket signals:

              connect(&socket_, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(sockStateChanged(QAbstractSocket::SocketState)));
              connect(&socket_, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sockErrorOccured(QAbstractSocket::SocketError)));
          

          sockStateChanged() and sockErrorOccured() only send messages to debug output with text from error list and states.
          They work fine during connection saying what is happening with socket:

          // if wire is plugged in
          State changed:  "The socket is performing a host name lookup."
          State changed:  "The socket has started establishing a connection."
          State changed:  "connection is established."
          // if not
          State changed:  "The socket is performing a host name lookup."
          State changed:  "The socket has started establishing a connection."
          State changed:  "The socket is not connected."
          Socket error occured:  "An error occurred with the network (e.g., the network cable was accidentally plugged out)."
          

          But when connection established they just stop working. If I plug out wire no signals would be emitted and state would not change (still ConnectedState). Even if I try to send something, there is no reaction (see UPD). If I plug wire back nothing happens (board/server will not receive/send data, no signals emitted).
          I tried to use VRonin method too, but it does not work (no disconnected() signal).

          QObject::connect(&socket_, &QAbstractSocket::disconnected, []()->void{qDebug("Disconnected");});
          

          After all only one solution seems to work for me: use timer to wait response and disconnect if there is nothing to read.

          // timer as class member
          QTimer readTimer;
          int readTimeout;
          //-----------------------
          void configureTimer() 
          {
              // configuring & connection to slot readReply()
              readTimer.setSingleShot(true);
              readTimer.setInterval(readTimeout);
              connect(&readTimer, SIGNAL(timeout()), this, SLOT(readReply()));
          }
          //-----------------------
          void sendRequest()
          {
              if (socket_.write(pingRequest_) == -1) {
                  // result is always 0 after connection, so we would not get here
                  qDebug() << "Request: sending failed";
                  return;
              }
              // timer will call readReply after waiting
              readTimer.start();
          }
          //-----------------------
          void readReply()
          {
              if (socket_.bytesAvailable() == 0 || !isConnected()) {
                 qDebug() << "No bytes available or disconnected");
                 // call reconnect
                 return;
              }
            
               QByteArray reply = socket_.readAll();
               //do something with reply
          }
          

          UPD:
          I found out that if you try to send data when wire is out after a ~20 sec timeout socket will close emitting all necessary signals.
          But it will stay Connected if you don't. I waited for several minutes and state was not changed.

          So you should send "ping" sometimes to know about disconnect in case if your application doesn't send data often. If your ping waits reply you can close socket by timeout, if not - wait for automatic closing.

          how did I get here?

          KroMignonK 1 Reply Last reply
          0
          • puzzled_giraffeP puzzled_giraffe

            Hi everyone.
            Topic is old, but problem still exists. I'm using QT 5.14.1 on Windows 7 and tried to compile project with MinGW(32/64) and MSVC17(32/64), but results are same: socket does not react on physical disconnect.
            It is important remark that I can't use blocking calls (like waitForBytesWritten() / waitForConnected() / etc) in my project.

            First I used next check (I think TS talked about something like this):

            bool IsConnected() {
                 return socket_.state() == QTcpSocket::ConnectedState;
            }
            //---- somewhere in code -----
            if(IsConnected()) {
               // do something;
            } else { /*error occured*/ }
            

            And I got same result: if wire was plugged out after connection state still was ::ConnectedState. Next I tried to use socket signals:

                connect(&socket_, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(sockStateChanged(QAbstractSocket::SocketState)));
                connect(&socket_, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sockErrorOccured(QAbstractSocket::SocketError)));
            

            sockStateChanged() and sockErrorOccured() only send messages to debug output with text from error list and states.
            They work fine during connection saying what is happening with socket:

            // if wire is plugged in
            State changed:  "The socket is performing a host name lookup."
            State changed:  "The socket has started establishing a connection."
            State changed:  "connection is established."
            // if not
            State changed:  "The socket is performing a host name lookup."
            State changed:  "The socket has started establishing a connection."
            State changed:  "The socket is not connected."
            Socket error occured:  "An error occurred with the network (e.g., the network cable was accidentally plugged out)."
            

            But when connection established they just stop working. If I plug out wire no signals would be emitted and state would not change (still ConnectedState). Even if I try to send something, there is no reaction (see UPD). If I plug wire back nothing happens (board/server will not receive/send data, no signals emitted).
            I tried to use VRonin method too, but it does not work (no disconnected() signal).

            QObject::connect(&socket_, &QAbstractSocket::disconnected, []()->void{qDebug("Disconnected");});
            

            After all only one solution seems to work for me: use timer to wait response and disconnect if there is nothing to read.

            // timer as class member
            QTimer readTimer;
            int readTimeout;
            //-----------------------
            void configureTimer() 
            {
                // configuring & connection to slot readReply()
                readTimer.setSingleShot(true);
                readTimer.setInterval(readTimeout);
                connect(&readTimer, SIGNAL(timeout()), this, SLOT(readReply()));
            }
            //-----------------------
            void sendRequest()
            {
                if (socket_.write(pingRequest_) == -1) {
                    // result is always 0 after connection, so we would not get here
                    qDebug() << "Request: sending failed";
                    return;
                }
                // timer will call readReply after waiting
                readTimer.start();
            }
            //-----------------------
            void readReply()
            {
                if (socket_.bytesAvailable() == 0 || !isConnected()) {
                   qDebug() << "No bytes available or disconnected");
                   // call reconnect
                   return;
                }
              
                 QByteArray reply = socket_.readAll();
                 //do something with reply
            }
            

            UPD:
            I found out that if you try to send data when wire is out after a ~20 sec timeout socket will close emitting all necessary signals.
            But it will stay Connected if you don't. I waited for several minutes and state was not changed.

            So you should send "ping" sometimes to know about disconnect in case if your application doesn't send data often. If your ping waits reply you can close socket by timeout, if not - wait for automatic closing.

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

            @puzzled_giraffe If you want your TCP socket to fast detect connection with counterpart is lost, you have to set KeepAliveOption. On Windows systems, you have to do this before connecting the socket.

                auto mySocket = new QTcpSocket();
                mySocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
                mySocket->connectToHost(...);
            

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

            puzzled_giraffeP 1 Reply Last reply
            2
            • KroMignonK KroMignon

              @puzzled_giraffe If you want your TCP socket to fast detect connection with counterpart is lost, you have to set KeepAliveOption. On Windows systems, you have to do this before connecting the socket.

                  auto mySocket = new QTcpSocket();
                  mySocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
                  mySocket->connectToHost(...);
              
              puzzled_giraffeP Offline
              puzzled_giraffeP Offline
              puzzled_giraffe
              wrote on last edited by puzzled_giraffe
              #19

              @KroMignon I googled it a bit and found that this option only enables "keep alive" mode on socket. Windows has a 2 hours default delay before first request, so it is not very useful if someone wants to get actual connection state.
              So we return to "heartbit ping", OS registry changing (to reduce default intervals) or low level socket configuring.

              I tried it in a code, so yes, it does not have an noticable effect without additional actions.

              how did I get here?

              KroMignonK 1 Reply Last reply
              0
              • puzzled_giraffeP puzzled_giraffe

                @KroMignon I googled it a bit and found that this option only enables "keep alive" mode on socket. Windows has a 2 hours default delay before first request, so it is not very useful if someone wants to get actual connection state.
                So we return to "heartbit ping", OS registry changing (to reduce default intervals) or low level socket configuring.

                I tried it in a code, so yes, it does not have an noticable effect without additional actions.

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

                @puzzled_giraffe said in QTcpSocket state always connected:

                I tried it in a code, so yes, it does not have an effect without additional actions.

                By googling in found this:

                The SO_KEEPALIVE socket option is valid only for protocols that support the notion of keep-alive (connection-oriented protocols). For TCP, the default keep-alive timeout is 2 hours and the keep-alive interval is 1 second. The default number of keep-alive probes varies based on the version of Windows.

                So for Windows, you can setup those settings like this:

                int fd = mySocket->socketDescriptor();
                int enableKeepAlive = 1;
                int maxIdle = 10;
                int count = 3;
                int interval = 2;
                int result;
                
                result = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));
                result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
                result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count));
                result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
                

                Take a look at https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-setsockopt 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)

                puzzled_giraffeP 1 Reply Last reply
                1
                • JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by JonB
                  #21

                  @puzzled_giraffe , @KroMignon
                  I will just throw in an observation based on my tests years ago. Please take what I say with a pinch of salt, I might be wrong, @KroMignon may know more than I do, but....

                  When I tried this out (under Windows) on a product we developed I actually found that the keep-alive stuff made the situation worse. Because it's testing all the time, I found that it actually noticed missing connections and dropped/closed them more than if I had nothing and left TCP to its own devices.

                  So do you really need to be heartbeat pinging?

                  1 Reply Last reply
                  0
                  • KroMignonK KroMignon

                    @puzzled_giraffe said in QTcpSocket state always connected:

                    I tried it in a code, so yes, it does not have an effect without additional actions.

                    By googling in found this:

                    The SO_KEEPALIVE socket option is valid only for protocols that support the notion of keep-alive (connection-oriented protocols). For TCP, the default keep-alive timeout is 2 hours and the keep-alive interval is 1 second. The default number of keep-alive probes varies based on the version of Windows.

                    So for Windows, you can setup those settings like this:

                    int fd = mySocket->socketDescriptor();
                    int enableKeepAlive = 1;
                    int maxIdle = 10;
                    int count = 3;
                    int interval = 2;
                    int result;
                    
                    result = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));
                    result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
                    result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count));
                    result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
                    

                    Take a look at https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-setsockopt for more details.

                    puzzled_giraffeP Offline
                    puzzled_giraffeP Offline
                    puzzled_giraffe
                    wrote on last edited by puzzled_giraffe
                    #22

                    @KroMignon said in QTcpSocket state always connected:

                    result = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));
                    result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
                    result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count));
                    result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));

                    TCP_KEEPIDLE / TCP_KEEPCNT / TCP_KEEPINTVL - linux options, aren't they?

                    So for windows I found next solution:
                    add this lib to your project *.pro file

                    LIBS += -lws2_32
                    

                    Next after socket connection you should use:

                    #include <Ws2tcpip.h>
                    //------
                    // socket is QTcpSocket*
                    if (socket->state() == QAbstractSocket::ConnectedState) {
                        int fd = socket->socketDescriptor();    
                        DWORD  dwBytesRet = 0;
                        
                        struct tcp_keepalive   alive;    // your options for "keepalive" mode    
                        alive.onoff = TRUE;              // turn it on    
                        alive.keepalivetime = 30000;     // delay (ms) between requests, here is 30s, default is 2h (7200000)    
                        alive.keepaliveinterval = 5000;  // delay between "emergency" ping requests, their number (6) is not configurable
                        /* So with this config  socket will send keepalive requests every 30 seconds after last data transaction when everything is ok.
                           If there is no reply (wire plugged out) it'll send 6 requests with 5s delay  between them and then close. 
                           As a result we will get disconnect after approximately 1 min timeout.
                        */
                        if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR) {    
                            QDebug() << "WSAIotcl(SIO_KEEPALIVE_VALS) failed with err#" <<  WSAGetLastError();    
                            return;    
                        }
                    }

                    how did I get here?

                    PangolinP 1 Reply Last reply
                    0
                    • puzzled_giraffeP puzzled_giraffe

                      @KroMignon said in QTcpSocket state always connected:

                      result = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));
                      result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
                      result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count));
                      result = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));

                      TCP_KEEPIDLE / TCP_KEEPCNT / TCP_KEEPINTVL - linux options, aren't they?

                      So for windows I found next solution:
                      add this lib to your project *.pro file

                      LIBS += -lws2_32
                      

                      Next after socket connection you should use:

                      #include <Ws2tcpip.h>
                      //------
                      // socket is QTcpSocket*
                      if (socket->state() == QAbstractSocket::ConnectedState) {
                          int fd = socket->socketDescriptor();    
                          DWORD  dwBytesRet = 0;
                          
                          struct tcp_keepalive   alive;    // your options for "keepalive" mode    
                          alive.onoff = TRUE;              // turn it on    
                          alive.keepalivetime = 30000;     // delay (ms) between requests, here is 30s, default is 2h (7200000)    
                          alive.keepaliveinterval = 5000;  // delay between "emergency" ping requests, their number (6) is not configurable
                          /* So with this config  socket will send keepalive requests every 30 seconds after last data transaction when everything is ok.
                             If there is no reply (wire plugged out) it'll send 6 requests with 5s delay  between them and then close. 
                             As a result we will get disconnect after approximately 1 min timeout.
                          */
                          if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR) {    
                              QDebug() << "WSAIotcl(SIO_KEEPALIVE_VALS) failed with err#" <<  WSAGetLastError();    
                              return;    
                          }
                      }
                      PangolinP Offline
                      PangolinP Offline
                      Pangolin
                      wrote on last edited by
                      #23

                      @puzzled_giraffe
                      QTcpsocket have not got "connectState" setup? I think qt use long tcp connection by default.

                      Speak less and do more . You are your own worst enemy.

                      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