简体   繁体   中英

Detect if connection has been dropped

I'm trying to detect when a connection has been dropped.

On this way, it only detects that the connection is no longer active when the internet is back, but not when it has been dropped actually.

int loop = 1;
long int msConn;

// Main thread
void connect() {
  // ...

  while (loop) {
    if ((sizeBytes = recv(sockfd, buffer, MAX_BUFFER_SIZE - 1, 0)) == -1) {
      cout << "Error: connection lost." << endl;

      sleep(15);
      connect();
      return;
    }

    // Update timestamp
    struct timeval tp;
    gettimeofday(&tp, NULL);
    msConn = tp.tv_sec * 1000 + tp.tv_usec / 1000;
  }
}

// Heartbeat thread
void checkConnection() {
  for(;;)  {
    struct timeval tp;
    gettimeofday(&tp, NULL);
    long int ms = tp.tv_sec * 1000 + tp.tv_usec / 1000;

    if (msConn != 0) {
      if ((ms - msConn) >= 10000) {
        msConn = 0;
        close(sockfd);
      }
    }

    sleep(15);
  }
}

recv() returns -1 on error (such as the connection being lost unexpectedly), 0 on graceful disconnect (which you are ignoring!) , and >0 for data successfully read. Change your loop to handle the case when recv() returns 0, otherwise your loop will not exit when the peer intentionally drops the connection on its end:

while (loop) {
    sizeBytes = recv(sockfd, buffer, MAX_BUFFER_SIZE - 1, 0);
    if (sizeBytes == -1) {
        cout << "Error: connection lost." << endl;
        close(sockfd);
        sleep(15);
        return;
    }

    if (sizeBytes == 0) {
        cout << "Connection disconnected by peer." << endl;
        close(sockfd);
        sleep(15);
        return;
    }

    // Update timestamp
    struct timeval tp;
    gettimeofday(&tp, NULL);
    msConn = tp.tv_sec * 1000 + tp.tv_usec / 1000;
}

With that said, if the connection is lost abnormally, it may take the OS a long time to detect that condition. You are implementing your own timeout to account for that, but if you are using the socket in blocking mode (the default behavior), it may take recv() a long time to exit (and thus can block your loop from exiting in a timely manner). You can use select() / epoll() , or setsockopt(SOL_SOCKET, SO_RCVTIMEO) , to avoid that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM