I have a client connect() to a server, and when idle, it times out after a couple hours. I added setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE...) with 1 sec but it didnt make a difference. Any clues on why keepalive wouldnt work? Would it make a difference if I used SOL_TCP instead of SOL_SOCKET? This is on Linux.
All modern browsers use persistent connections as long as the server has Keep-Alive enabled. In order to check if your pages are delivered with a Keep-Alive header, you can use the HTTP Header Checker tool. This will display the Connection: Keep-Alive field if the HTTP Keep-Alive header is enabled.
The KeepAlive mechanism does this by sending low-level probe messages to see if the other side responds. If it does not respond to a certain number of probes within a certain amount of time, then it assumes the connection is dead and the process using the socket will then detect this through an error indication.
The TCP Keepalive Timer feature provides a mechanism to identify dead connections. When a TCP connection on a routing device is idle for too long, the device sends a TCP keepalive packet to the peer with only the Acknowledgment (ACK) flag turned on.
int val = 1;
setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof val)
Just enables keepalives. You will get the default timers for keepalive probes, which you can view with the command:
sysctl net.ipv4.tcp_keepalive_time
Normally the default is couple of hours.
If you want to change the default timers, you could use this:
struct KeepConfig cfg = { 60, 5, 5};
set_tcp_keepalive_cfg(fd, &cfg);
With the helper functions here:
struct KeepConfig {
/** The time (in seconds) the connection needs to remain
* idle before TCP starts sending keepalive probes (TCP_KEEPIDLE socket option)
*/
int keepidle;
/** The maximum number of keepalive probes TCP should
* send before dropping the connection. (TCP_KEEPCNT socket option)
*/
int keepcnt;
/** The time (in seconds) between individual keepalive probes.
* (TCP_KEEPINTVL socket option)
*/
int keepintvl;
};
/**
* enable TCP keepalive on the socket
* @param fd file descriptor
* @return 0 on success -1 on failure
*/
int set_tcp_keepalive(int sockfd)
{
int optval = 1;
return setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
}
/** Set the keepalive options on the socket
* This also enables TCP keepalive on the socket
*
* @param fd file descriptor
* @param fd file descriptor
* @return 0 on success -1 on failure
*/
int set_tcp_keepalive_cfg(int sockfd, const struct KeepConfig *cfg)
{
int rc;
//first turn on keepalive
rc = set_tcp_keepalive(sockfd);
if (rc != 0) {
return rc;
}
//set the keepalive options
rc = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, &cfg->keepcnt, sizeof cfg->keepcnt);
if (rc != 0) {
return rc;
}
rc = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &cfg->keepidle, sizeof cfg->keepidle);
if (rc != 0) {
return rc;
}
rc = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &cfg->keepintvl, sizeof cfg->keepintvl);
if (rc != 0) {
return rc;
}
return 0;
}
Despite its name, keep-alive is not about keeping connection alive, it is about exchanging packets periodically to make sure that there is a network path between peers. It kills connections that would survive extended network outages while idle.
Due to this behavior, keep-alive should not be used unless there is good reason, like telnet or SSH connections where it is reasonable to kill the session when client gets out of touch.
Most probably it is the server that is closing connection after n hours regardless of keepalive usage, due to some connection handling policy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With