You are viewing an old version of this page. View the current version.
Compare with Current View Page History
Version 1 Current »
当一个 TCP 连接建立之后,启用 TCP Keepalive 的一端便会启动一个计时器,当这个计时器数值到达 0 之后(也就是经过tcp_keep-alive_time时间后,这个参数之后会讲到),一个 TCP 探测包便会被发出。这个 TCP 探测包是一个纯 ACK 包(RFC1122#TCP Keep-Alives规范建议:不应该包含任何数据,但也可以包含1个无意义的字节,比如0x0),其 Seq号 与上一个包是重复的,所以其实探测保活报文不在窗口控制范围内。如果一个给定的连接在两小时内(默认时长)没有任何的动作,则服务器就向客户发一个探测报文段,客户主机必须处于下表中的4个状态之一。
详细解释一下就是:1)客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常的,服务器在两小时后将保活定时器复位。2)客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务端将不能收到对探测的响应,并在75秒后超时。服务器总共发送10个这样的探测 ,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。3)客户主机崩溃并已经重新启动。服务器将收到一个对其保活探测的响应,这个响应是一个复位,使得服务器终止这个连接。4)客户机正常运行,但是服务器不可达,这种情况与2类似,TCP能发现的就是没有收到探测的响应。直观来说,TCP KeepAlive的交互过程大致如下图所示:
以linux内核为例,应用程序若想使用TCP Keepalive,需要设置SO_KEEPALIVE套接字选项才能生效。
SO_KEEPALIVE
对应的,有三个重要的参数:
tcp_keepalive_time,在TCP保活打开的情况下,最后一次数据交换到TCP发送第一个保活探测包的间隔,即允许的持续空闲时长,或者说每次正常发送心跳的周期,默认值为7200s(2h)。
tcp_keepalive_time
7200s(2h)
tcp_keepalive_probes
9(次)
tcp_keepalive_intvl
75s
Keepalive 技术只是TCP协议中的一个可选项。因为不当的配置可能会引起一些问题,所以默认是关闭的。
具体来说,可能导致下列问题:
不可否认,TCP协议作为TCP/IP协议族中最重要部分,对互联的发展确实功不可没。但如今移动网络时代,无线通信越来越普及,作为上个世纪中期发明的TCP协议来说,客观的讲,在某些场景下确实有先天不足。那么,既然TCP协议本身有KeepAlive,为什么还要自已在应用层实现网络保活/心跳机制?
以移动端IM应用为例:
所以说,IM应用层自已做网络保活(心跳机制)是不可避免的。