I have heard of HTTP keep-alive but for now I want to open a socket connection with a remote server.
Now will this socket connection remain open forever or is there a timeout limit associated with it similar to HTTP keep-alive?
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.
Description. Once a TCP connection has been established, that connection is defined to be valid until one side closes it. Once the connection has entered the connected state, it will remain connected indefinitely. But in reality the connection will not last indefinitely.
What is TCP keepalive? The keepalive concept is very simple: when you set up a TCP connection, you associate a set of timers. Some of these timers deal with the keepalive procedure. When the keepalive timer reaches zero, you send your peer a keepalive probe packet with no data in it and the ACK flag turned on.
There is no limit in the TCP connection itself. Client and server could in theory stay connected for years without exchanging any data and without any packet flow. Problems are usually caused by middleboxes like NAT router or firewalls which keep a state and expire the state after some inactivity.
Does a TCP socket connection have a "keep alive"?
The short answer is yes there is a timeout enforced via TCP Keep-Alive, so no the socket won't remain open forever but will probably time out after a few hours.
If you would like to configure the Keep-Alive timeout on your machine, see the "Changing TCP Timeouts" section below. Otherwise read through the rest of the answer to learn how TCP Keep-Alive works.
TCP connections consist of two sockets, one on each end of the connection. When one side wants to terminate the connection, it sends an RST
packet which the other side acknowledges and both close their sockets.
Until that happens, however, both sides will keep their socket open indefinitely. This leaves open the possibility that one side may close their socket, either intentionally or due to some error, without informing the other end via RST
. In order to detect this scenario and close stale connections the TCP Keep Alive process is used.
There are three configurable properties that determine how Keep-Alives work. On Linux they are1:
tcp_keepalive_time
tcp_keepalive_probes
tcp_keepalive_intvl
The process works like this:
tcp_keepalive_time
seconds, send a single empty ACK
packet.1 ACK
of its own? tcp_keepalive_intvl
seconds, then send another ACK
ACK
probes that have been sent equals tcp_keepalive_probes
.RST
and terminate the connection.This process is enabled by default on most operating systems, and thus dead TCP connections are regularly pruned once the other end has been unresponsive for 2 hours 11 minutes (7200 seconds + 75 * 9 seconds).
Since the process doesn't start until a connection has been idle for two hours by default, stale TCP connections can linger for a very long time before being pruned. This can be especially harmful for expensive connections such as database connections.
According to RFC 1122 4.2.3.6, responding to and/or relaying TCP Keep-Alive packets is optional:
Implementors MAY include "keep-alives" in their TCP implementations, although this practice is not universally accepted. If keep-alives are included, the application MUST be able to turn them on or off for each TCP connection, and they MUST default to off.
...
It is extremely important to remember that ACK segments that contain no data are not reliably transmitted by TCP.
The reasoning being that Keep-Alive packets contain no data and are not strictly necessary and risk clogging up the tubes of the interwebs if overused.
In practice however, my experience has been that this concern has dwindled over time as bandwidth has become cheaper; and thus Keep-Alive packets are not usually dropped. Amazon EC2 documentation for instance gives an indirect endorsement of Keep-Alive, so if you're hosting with AWS you are likely safe relying on Keep-Alive, but your mileage may vary.
Unfortunately since TCP connections are managed on the OS level, Java does not support configuring timeouts on a per-socket level such as in java.net.Socket
. I have found some attempts3 to use Java Native Interface (JNI) to create Java sockets that call native code to configure these options, but none appear to have widespread community adoption or support.
Instead, you may be forced to apply your configuration to the operating system as a whole. Be aware that this configuration will affect all TCP connections running on the entire system.
The currently configured TCP Keep-Alive settings can be found in
/proc/sys/net/ipv4/tcp_keepalive_time
/proc/sys/net/ipv4/tcp_keepalive_probes
/proc/sys/net/ipv4/tcp_keepalive_intvl
You can update any of these like so:
# Send first Keep-Alive packet when a TCP socket has been idle for 3 minutes $ echo 180 > /proc/sys/net/ipv4/tcp_keepalive_time # Send three Keep-Alive probes... $ echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes # ... spaced 10 seconds apart. $ echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl
Such changes will not persist through a restart. To make persistent changes, use sysctl
:
sysctl -w net.ipv4.tcp_keepalive_time=180 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_keepalive_intvl=10
The currently configured settings can be viewed with sysctl
:
$ sysctl net.inet.tcp | grep -E "keepidle|keepintvl|keepcnt" net.inet.tcp.keepidle: 7200000 net.inet.tcp.keepintvl: 75000 net.inet.tcp.keepcnt: 8
Of note, Mac OS X defines keepidle
and keepintvl
in units of milliseconds as opposed to Linux which uses seconds.
The properties can be set with sysctl
which will persist these settings across reboots:
sysctl -w net.inet.tcp.keepidle=180000 net.inet.tcp.keepcnt=3 net.inet.tcp.keepintvl=10000
Alternatively, you can add them to /etc/sysctl.conf
(creating the file if it doesn't exist).
$ cat /etc/sysctl.conf net.inet.tcp.keepidle=180000 net.inet.tcp.keepintvl=10000 net.inet.tcp.keepcnt=3
I don't have a Windows machine to confirm, but you should find the respective TCP Keep-Alive settings in the registry at
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters
Footnotes
1. See man tcp
for more information.
2. This packet is often referred to as a "Keep-Alive" packet, but within the TCP specification it is just a regular ACK
packet. Applications like Wireshark are able to label it as a "Keep-Alive" packet by meta-analysis of the sequence and acknowledgement numbers it contains in reference to the preceding communications on the socket.
3. Some examples I found from a basic Google search are lucwilliams/JavaLinuxNet and flonatel/libdontdie.
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