Sending Heart beats to client, to keep socket connection alive?

Hello,
I have set a 2 minute time out on recv() using setsockopt (client side).
To keep socket connection alive, server sends a heartbeat to all connected clients every minute (to which client responds back).

On the other hand if client does not receive anything from server in two minutes, it establishes a new connection.

Problem is, some clients get timed out after 2 minutes even though the heartbeat signal was received successfully and replied back to.

How is that possible?

1
2
3
4
5
6
7
8
9
10
11
12
//client
ZeroMemory(buf, 4096);
int bytesReceived;
setsockopt(SendingSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
bytesReceived = recv(SendingSocket, buf, 4096, 0);	
	if (bytesReceived > 0)
	{
             if (strcmp("R U ALIVE?", buf) == 0)//heartbeat signal
		{
			send(SendingSocket, "yes", strlen("yes") + 1, 0);//ack
		}
        }

My aim is to keep connection alive by using heartbeat.

Thanks.
Last edited on
Neither send() nor recv() guarantee to preserve message boundaries (for TCP at least - UDP is different).

You might try and send("yes"), but it might only get as far as sending "y" before returning with a 'partially successful' result. You need to watch out for this.

Similarly, just because you send "yes" successfully in a single call, the remote recv() might only get as far as "ye" before returning.

Fragmentation and reassembly are problems you need to address at both ends.
Thanks for responding, I did not quite grasp what you mentioned. If client receives something and responds back (even with partial data "ye" or "y" instead of "yes") the connection must not timeout.
Well you need to ensure that the whole response is sent.
Eg.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ssize_t mySend(int sock, const void *buf, size_t len ) {
    ssize_t result;
    const char *bp = buf;
    do {
        result = send(sock, bp, len, 0);
        if ( result > 0 ) {
            len -= result;
            bp += result;
        }
        // if result == -1 && ( errno == EAGAIN || errno == EINTR )
        // might be special cases you want to consider.
    } while ( len > 0 && result > 0 );
    return result;
}

If the first send() is only partially successful, then len will not be decremented to zero and the loop will repeat until the whole 'len' bytes of buf are sent.

recv() has to do something similar as well, only this time, you have to find the message boundary (which looks like \0 from your send).
You have to cater for receiving "R U ALIVE?\0" or "R U " followed by "ALIVE?\0".

On particularly laggy connections, you might end up with "R U ALIVE?\0R U" in a single recv() call (that is, your message separator is in the middle of the buffer).
Topic archived. No new replies allowed.