网页浏览总次数

2010年11月20日星期六

TCP Keepalive HOWTO

原文参考 http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/

TCP连接有很多定时器,其中一些与Keepalive有关。当这些定时器计数为0时,就会发送Keepalive探帧包(我记得在最早的BSD代码上该探帧包占一个序列号Sequence)。如果这些包没有得到对端的ACK回应,则可采取一定的控制策略,比如继续发送探帧包或认为对端已非正常中断连接。

Keepalive的用途主要有两个:检查对端是否死掉或者防止因网络无活动而连接中断。假设A和B建立了一个TCP连接,B突然死掉了,A会在一定时间后发送Keepalive探帧包,如果B重启后收到了探帧包,因TCP套接字对不上或TCP序列号对不上,会导致B给A发送RST包,此时连接马上中断。如果B一直没活过来,则发送一定数量的探帧包后A认为连接中断。这是有效检查对端死掉的情况,还有一种情况是通过NAT或代理上网,如果A和B之间隔着NAT或代理,这些NAT或者代理通常有一定的连接超时控制,发现A和B在一段时间后没有交换数据,就会切断二者的通信,此时用Keepalive可避免这种情况。

Linux下控制Keepalive的参数有三个:

tcp_keepalive_time 在连接多长时间没有数据交换时发送探帧包
tcp_keepalive_intvl 发送下一个探帧包距离发送本次探帧包的时间间隔
tcp_keepalive_probes 发送多少次没有回应的探帧包后认为对端死掉

对应在proc文件系统的位置是

/proc/sys/net/ipv4/tcp_keepalive_time
/proc/sys/net/ipv4/tcp_keepalive_intvl
/proc/sys/net/ipv4/tcp_keepalive_probes

注意:仅仅配置内核参数是不够的,还必须在编程的时候设置套接字的选项,调用函数是

int setsockopt(int s, int level, int optname,
const void *optval, socklen_t optlen)

选项为SO_KEEPALIVE,此外还可以设置TCP选项(设置的level为SOL_TCP而不是SOL_SOCKET)覆盖系统全局设置

TCP_KEEPCNT 与tcp_keepalive_probes对应
TCP_KEEPIDLE 与tcp_keepalive_time对应
TCP_KEEPINTVL 与tcp_keepalive_intvl对应

如果有些程序无法修改源码,可采用libkeepalive覆盖程序的socket调用,达到设置这些选项的目的,为socket调用提供覆盖的是ld的PRELOAD机制。假设待覆盖的程序为test,则

$ LD_PRELOAD=libkeepalive.so \
KEEPCNT=20 \
KEEPIDLE=180 \
KEEPINTVL=60 \
test

可修改test程序的socket选项。

关于libkeepalive项目可参考 http://libkeepalive.sourceforge.net/

没有评论:

发表评论