TCP的keepalive

TCP的keepalive

TCP的keepalive

一般是服务端开启这个功能,当然双方都可以使用。对于客户端来说会处于以下四种状态之一:
1.客户主机依然正常运行,并从服务器可达。客户端的TCP响应正常,而服务端也知道对方是正常工作的,服务器再两小时以后将keepalive定时器复位。如果在两个小时定时器时间达到之前有应用程序的通信量通过此连接,则定时器在交换数据后的未来2小时再复位。

2.客户端主机已崩溃,并且关闭或者正在重启。在任何一种情况下,客户端的TCP都没有响应。服务器将不能够收到对探查的响应,并在75秒后超时。服务器总共发送10个这样的探查,每个间隔75秒,如果服务器没有收到一个响应,它就认为客户端主机已经关闭并终止连接。

3.客户端主机崩溃并重新启动。这时服务端将收到一个对其keepalive活动探查的响应,但是这个响应是一个复位,使得服务端终止这个连接。

4.客户端主机正常运行,但是从服务端不可达,这与状态2相同,因为TCP不能够区分状态2和状态4的区别,它所能发现的就是没有收到探查的响应。

修改TCP的keepalive相关参数:

# cat /proc/sys/net/ipv4/tcp_keepalive_time  
7200  
# cat /proc/sys/net/ipv4/tcp_keepalive_intvl  
75    
# cat /proc/sys/net/ipv4/tcp_keepalive_probes  
9  

第一个是多长时间做一次keepalive检查,默认是2小时
第二个是当触发keepalive检查后连接不同,再触发一个探查(一个另外的检查),每次探查的时间间隔
第三个是触发多少次探查
修改之后需要重启网络

/etc/init.d/network restart  

对于java的服务端来说,需要指定打开keepalive选项
使用tcpdump辅助观察,抓包命令

tcpdump  -i lo port 7040 -nn -X   

使用iptables封住ip

#封ip  
iptables -t filter -A INPUT -s ip_addr  -j DROP  
  
#封进入的端口  
iptables -t filter -A INPUT  -p tcp --dport 8000 -j DROP  
  
#封出去的端口  
iptables -t filter -A OUTPUT -p tcp --dport 8000 -j DROP  
  
#允许某个出去的端口  
iptables -t filter -A OUTPUT -p tcp --dport 9999 -j ACCEPT  
  
#查看iptables内容  
iptables -L -n  
  
#清空iptables  
iptables -F   

 

keepalive的四种情况

1.正常的keepalive如下:

首先这里修改了keepalive检查时间为30秒。
最上面三行是三次握手,三次握手之后客户端(客户端是1135)和服务端没有任何应用层的数据交换。
过了一段时间(实际是上超过了30秒,不知道为何)看到服务端发送一个keepalive给客户端,客户端在返回一个ack。之后又过了一段时间又是一个keepalive检查包和ack应答。
这里可以看到keepalive确实起到作用了,它相当于一个后台线程,某某的运行,一段时间之后就会发送一个心跳包检查对方是否存活。

2.keepavlie检查超时

当服务端触发keepalive检查后,发现客户端无法连接,就会尝试经过75秒后(默认值)再次尝试发送一个心跳包检查,一直发送9次,如果这期间没有一个响应的话,就认为对方不可达,发送一个复位标志。(图片中绿色遮住的是服务端,红色遮住的是客户端,之后图片也是一样)
而客户端的连接还保持着在,如果恢复网络(iptables解封),服务端不会发送任何数据给客户端了。因为服务端认为客户端已经死掉了。此时如果客户端再给服务端发送数据的话,服务端会返回一个复位标志。

3.客户端已经崩溃或者重启

以上两个主机之间用iptables相互封住了,互相ping都ping不同。
在图中可以看到服务端发送了几次keepalive检查后发现无法连同,然后发起了75秒一次的探查,最后客户端kill -9 强行杀掉了这个连接。最后红色的遮住的线,也就是客户端发送了一个fin包,这个可能是操作系统发送的包,所以iptables没有拦住,最后导致服务端发送复位标志。
这里的演示和《TCP/IP详解》里面的还不同,那里的演示中是直接拔掉了网线,然后关闭进程再插上网线,如果之后服务端触发了keepalive的话,会收到客户端的复位标志。

4.另一端不可达

两段的主机都是正常的,进程也正常,但是中间的网络不通,比如途径的路由器突然重启了等情况。
这时候服务端发送keepalive检查的时候,会收到一个ICMP差错报文,但是这个错误对于TCP来说只是一个软错误,它会继续尝试9次(每隔75秒一次的探查)如果每次都是ICMP不可达或者对方主机无响应,那么最终会发送一个复位报文段,将这个连接终止。

参考

TCP-Keepalive-HOWTO
闲说HeartBeat心跳包和TCP协议的KeepAlive机制
linux下IPTABLES配置详解
iptables详解

 

13 次阅读

发表评论

电子邮件地址不会被公开。