Reputation: 1152
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);
}
}
Upvotes: 1
Views: 391
Reputation: 598011
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.
Upvotes: 2