RFC 1122 要求,tcp默认的keepalive不能短于2小时,
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval. This interval MUST be configurable and MUST default to no less than two hours.
然而很多路由器连接追踪的老化时间,比较短,如小米高通ax3000:
# cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
1800
对于一个长连接,此时必须将保活时间设置的短一些。否则路由器nat条目被老化,链路就不通了。
保活时间有3个参数:
tcp_keepalive_time = 7200
tcp_keepalive_intvl = 75
tcp_keepalive_probes = 9
分别用tcp选项:TCP_KEEPIDLE、TCP_KEEPINTVL、TCP_KEEPCNT读取和设置。
第一个参数是触发keepalive的时间,也就是超过这个时间没有数据包,就认为tcp连接变成idle了,会发送keep alive包。
第二个参数控制keep alive包发送的间隔。
如果idle时间比较小,比如设置为5s。那第一个keep alive发送后5s,也不会立即再发送keep alive。
它需要满足,两个keep alive包的间隔不小于tcp_keepalive_intvl。
第三个参数是如果连接断掉了,最多发送多少个keep alive。
另外,还有一个特别要注意的,要开启keep alive功能,还需要设置 SOL_SOCKET, SO_KEEPALIVE,打开。默认是关闭的。
参考
rfc 1122. https://www.freesoft.org/CIE/RFC/1122/114.htm
https://unix.stackexchange.com/questions/519501/default-tcp-keepalive-settings
https://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
man 7 tcp