Crab213's Blog.

TCP/IP详解阅读笔记5:TCP心跳机制

2016/03/19

根据TCP的实现机制,只要TCP协议的两端不出现重启,或者更换IP地址,并且不关闭TCP连接的话,TCP连接就会一直维持,至少原理上是这样。TCP连接在双方都处于闲置状态时,TCP两端不会发送接受任何信息。但是有些情况下,我们是需要知道对面是否关闭或者丢失了连接,或者我们想要保持一个最小限度的连接流,哪怕TCP两端实际上没有需要交换的数据。TCP心跳(keepalive)机制提供了这样的功能。TCP心跳机制提供了一种在不干扰正常通讯内容前提下检测网络另一头的方法。它控制一个心跳检测定时器,每当定时器到时时,发出一个心跳检测,接受端收到这个检测时,会发回一个ACK。

TCP心跳机制是一个很有争议的机制。一些人认为轮询操作应该由应用层实现,但是另一卸任认为既然有多应用都需要轮询机制,那么TCP协议就应该支持它。TCP心跳机制是可选的,在建立连接的时候,客户端可以自行选择是否启用(socket中有对应选项)。但是TCP心跳也有可能是一些本来正常的连接提前关闭。比如,如果有一个连接临时的出现网络通讯方面的问题,那么在没有TCP心跳的时候,如果网络恢复正常,这个连接还是可以继续使用的,但是一旦开启TCP心跳,这个连接就会被服务端当作丢失的连接而关闭。

TCP心跳是为给服务器检测客户端是否存活而生的。一些服务器需要处理大量的连接,如果一些客户端不正常关闭或者丢失了连接,那么如果服务器还是把这些连接当作正常连接而继续进行等待的话,很快就会耗尽服务器的资源。所以服务器需要检测到这中连接,并将其关闭。一些提供相对较短时间的服务的服务端如HTTP,IMAP,POP,会比较适合TCP心跳机制。而提供长时间服务的服务端如SSH,可能并不需要TCP心跳机制。但是假如SSH两端通过NAT进行通信,长时间的闲置会使NAT服务器认为这个连接超时,从而关闭连接,这时SSH就会需要TCP心跳包了。

TCP心跳实现

TCP连接默认是不启用心跳机制的,但是连接两端可以自由选择是否开启心跳机制。一旦开启心跳机制,当连接闲置一定时间,到达心跳检测时间(keepalive time),就会发送心跳包,每隔心跳包间隔时间(keepalive interval)就会发送一个心跳包,发够总心跳包数(keepalive probes)时,如果没有收到ACK,那么就认为连接需要关闭。上面几个参数大部分操作系统都可以自行设置。

心跳包是一个携带数据为零字节或者一字节的TCP段,这个段的确认序列数(ACK)比当前心跳包发送方收到的最大ACK数少1,实际上就是一个重复的包,携带着垃圾数据。心跳包丢失后不会被重发,在心跳包没有收到ACK一定次数后,认为连接丢失。需要注意的是有些系统(大部分为旧系统)的TCP实现并不会回应空的心跳包。

CATALOG
  1. 1. TCP心跳实现