一、TCP存活(keepalive)检测的背景

对于TCP设计来说,如果一个客户端和服务器端建立连接后,不在进行数据传输,那么这个连接将会一直存在下去,理论上即使中间的路由器崩溃重启、或者中间的网络线路拔掉在插上等等,只要客户端和服务器端的主机没有发生异常,这个TCP连接仍然是处于连接状态的。这样会有两个问题

1、服务器端可能需要内存等资源保存每个连接的状态信息,即使这个连接在实际上已经不能通信而没有存在的必要了。比如客户端崩溃时,服务器可能仍然认为这个连接是有效的而继续占用为这个连接分配的资源

2、防火墙和NAT设备可能会保存一个连接超时的定时器,如果这个TCP连接长时间没有数据传输,定时器超时后,服务器端和客户端实际上已经不能在进行通信。

为了解决上面的两个问题,TCP连接需要一个存活(keepalive)检测机制,定时检测当前的TCP连接是否可用,以刷新防火墙和NAT信息,或者当检测到连接失败的时候释放相关资源。

二、存活检测的两种方式:

1、应用层面的心跳机制(application-managed keepalive)

自定义心跳消息头. 一般客户端主动发送, 服务器接收后进行回应(也可以不回应)。相比传输层的keepalive检测,应用层的检测更灵活且不依赖传输层的协议。 例如最新的ssh就有应用层的存活检测机制。本文不做额外介绍。

2、传输层的存活检测

TCP的存活检测就属于传输层的存活检测功能,相比于应用层的检测,传输层的检测可以提供更通用的检测从而减少应用层的工作量,另外传输层的探测包不需要添加应用层的头,从而减轻了网络负载。传输层的TCP keepalive是接下来介绍的功能。

三、TCP的存活检测

TCP keealive定义于RFC1122,但是并不是要求每个TCP实现都支持keepalive,[RFC1122]给出的原因是(1)在短暂的故障期间,它们可能引起一个良好连接被释放,比如网络中间的路由器崩溃了并且正在重启,keepalive检测可能会认为对端主机崩溃而释放连接,实际上在这种情况下路由器重启完毕后,该TCP连接可以继续通信;(2)需要消耗额外的带宽资源;(3)在以数据包计费的互联网上需要额外花费金钱;但是尽管如此,很多TCP实现还是支持TCP的存活检测。

3.1、TCP存活检测的机制

TCP的存活检测可以在TCP连接的两端同时启用,或者只在一端启用,或者两端都不启用。在TCP的存活检测中有三个参数

keepalive time:存活检测时间间隔

keepalive interval:没有收到ACK响应时存活检测时间间隔

keepalive probes:没有收到ACK响应时存活检测累计次数,因为keepalive依靠探测包的ACK响应判断连接情况,但是不携带数据的ACK没有重传不是可靠的传输,因此需要多次累计探测没有响应才能认为连接失活。

TCP的存活检测流程如下:在TCP存活检测中有一个存活定时器(keepalive timer),当TCP连接的任何一个方向有业务数据传输时就会把这个存活定时器重置为keepalive time,当没有数据传输本端这个定时器超时的时候,TCP就会发送一个探测包(keepalive probe 或者简称为keepalive包),对端接收到这个探测包后就会响应一个ACK,本端接收到这个ACK响应的时候就会重置这个存活定时器为keepalive time。如果本端没有收到这个ACK响应,会以keepalive interval为间隔时间重复发送探测包,如果一直发送了keepalive probes次都没有收到ACK响应,则认为这个连接已经失活。如果中间的某次收到ACK响应则会重置存活定时器为keepalive time,并且停止keepalive interval为间隔的探测包重复发送。

3.2、探测包的包格式

对于探测包的格式,一般是使用本端目前发送窗口的上一个byte做为系列号,比如当前本端接受到的最大连续ACK Number为n,则探测包的seq为n-1;按照RFC1122,探测包中可以不包含数据,也可以包含1byte的无用数据(garbage byte)以兼容老式TCP实现。

3.3、TCP存活检测可以检测到的连接情况

TCP的存活检测可以检测到四种连接情况,在下面的描述中,我们称使用存活选项的那一段为服务器,另一端为客户端。也可以在客户端设置该选项,且没有不允许这样做的理由,但通常设置在服务器。如果连接两端都需要探测对方是否消失,那么就可以在两端同时设置(比如NFS)。

1)客户端主机依旧活跃(up)运行,并且从服务器可到达。从客户端TCP的正常响应,服务器知道对方仍然活跃。服务器的TCP复位存活定时器为keepalive time,如果在keepalive time到期之前,连接上发生应用程序的通信,则TCP会将存活定时器重置为keepalive time。

2)
客户端已经崩溃,或者已经关闭(down),或者正在重启过程中。在这两种情况下,它的TCP都不会响应。服务器没有收到对其发出探测的响应,并且在keepalive interval秒之后超时。服务器将总共发送keepalive probes个这样的探测,每个探测间隔keepalive interval秒。如果没有收到一个响应,它就认为客户端主机已经关闭并终止连接。

3) 客户端曾经崩溃,但已经重启。这种情况下,服务器将会收到对其存活探测的响应,但该响应是一个复位(在TCP头中置位RST标识),从而引起服务器对连接的终止。

4) 客户端主机活跃运行,但从服务器不可到达。这与状态2类似(但是状态4可能会收到ICMP的错误指示信息),因为TCP无法区别它们两个。它所能表明的仅是未收到对其探测的回复。

服务器不必担心客户端主机被关闭然后重启的情况(这里指的是操作员执行的
正常关闭,而不是主机的崩溃)。当系统被操作员关闭时,所有的应用程序进程(也就是客户端进程)都将被终止,客户端TCP会在连接上发送一个FIN。收到
这个FIN后,服务器TCP向服务器进程报告一个文件结束,以允许服务器检测这种状态。

在第一种状态下,服务器应用程序不知道存活探测是否发生。凡事都是由
TCP层处理的,存活探测对应用程序透明,直到后面2,3,4三种状态发生。在这三种状态下,通过服务器的TCP,返回给服务器应用程序错误信息。(通常
服务器向网络发出一个读请求,等待客户端的数据。如果存活检测返回一个错误信息,则将该信息作为读操作的返回值返回给服务器。)在状态2,错误信息类似于
“连接超时”。状态3则为“连接被对方复位”。第四种状态看起来像连接超时,或者根据是否收到与该连接相关的ICMP错误信息,而可能返回其它的错误信息。

四、TCP存活检测的相关参数设置

在各个系统下三个参数对应如下表,括号中给出的是系统的默认值,其中keepalive probs参数在FreeBSD和Mac OS X下为常量。另外在FreeBSD和Mac OS X这两个系统下还有一个net.inet.tcp.always_keepalive的布尔变量,如果这个变量使能,则所有的TCP连接都会有keepalive功能,即使应用程序没有请求keepalive功能(Linux通过libkeepalive库也可以实现相似功能)。其中Windows系统下的参数在注册表[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]下

keepalive time keepalive interval keepalive probs
Linxu net.ipv4.tcp_keepalive_time(7200) net.ipv4.tcp_keepalive_intvl(75) net.ipv4.tcp_keepalive_probes(9)
FreeBSD net.inet.tcp.keepidle(7200) net.inet.tcp.keepintvl(75) 8
Mac OS X net.inet.tcp.keepidle(7200) net.inet.tcp.keepintvl(75) 9
Windows KeepAliveTime(7200) KeepAliveInterval(1) MaxDataRetries(5)

RFC1122中规定keepalive time默认不能少于2小时,另外keepalive功能必须默认关闭,除非应用程序请求使用keepalive功能(FreeBSD和Mac OS X系统下net.inet.tcp.always_keepalive设置是违反这个行为的)。

五、wireshark示例

1、通过linux的socket选项,设置keepalive time=5s、keepalive interval=1s、keepalive probes=3。最终如下图所示

client在与server端建立连接后,双发并没有数据进行传输,server每隔5s进行一次keepalive探测,但是No10探测包没有收到client的回复,因此server端又隔了1s重复进行探测,最终发送了三个探测包No10、No11、No12后,server端放弃探测,认定与client端的连接已经断开,因此最后发送一个RST报文后,server端也会释放这个连接。

TCP系列37—Keep Alive—1、TCP存活检测的更多相关文章

  1. TCP系列11—重传—1、TCP重传概述

    在最开始介绍TCP的时候,我们就介绍了TCP的三个特点,分别是面向连接.可靠.字节流式.前面内容我们已经介绍过了TCP的连接管理,接下来的这部分内容将会介绍与TCP可靠性强关联的TCP重传. 很多网络 ...

  2. TCP系列01—概述及协议头格式

    一.TCP简单介绍 我们经常听人说TCP是一个面向连接的(connection-oriented).可靠的(reliable).字节流式(byte stream)传输协议,  TCP的这三个特性该怎么 ...

  3. 网游中的网络编程系列1:UDP vs. TCP

    原文:UDP vs. TCP,作者是Glenn Fiedler,专注于游戏网络编程相关工作多年. 目录 网游中的网络编程系列1:UDP vs. TCP 网游中的网络编程2:发送和接收数据包 网游中的网 ...

  4. TCP系列44—拥塞控制—7、SACK关闭的快速恢复

    ) return;    delta = ssthresh - in_flight;     prr_delivered += newly_acked_sacked; if (delta < 0 ...

  5. TCP系列16—重传—6、基础快速重传(Fast Retransmit)

    一.快速重传介绍 按照TCP协议,RTO超时重传是一个非常重要的事件,当RTO超时的时候,TCP会同时通过两种方式非常谨慎的降低发送数据包的速率,一种是基于拥塞控制削减发送窗口的大小,另外一个是通过指 ...

  6. TCP系列08—连接管理—7、TCP 常见选项(option)

    一.TCP选项概述 在前面介绍TCP头的时候,我们说过tcp基本头下面可以带有tcp选项,其中有些选项只能在连接过程中随着SYN包发送,有些可以延后.下表汇总了一些tcp选项 其中我标记为红色的部分是 ...

  7. TCP系列07—连接管理—6、TCP连接管理的状态机

            经过前面对TCP连接管理的介绍,我们本小节通过TCP连接管理的状态机来总结一下看看TCP连接的状态变化 一.TCP状态机整体状态转换图(截取自第二版TCPIP详解) 二.TCP连接建立 ...

  8. TCP系列05—连接管理—4、TCP连接的ISN、连接建立超时及TCP的长短连接

    一.TCP连接的ISN         之前我们说过初始建立TCP连接的时候的系列号(ISN)是随机选择的,那么这个系列号为什么不采用一个固定的值呢?主要有两方面的原因 防止同一个连接的不同实例(di ...

  9. TCP系列04—连接管理—3、TCP连接的半打开和半关闭

    在前面部分我们我们分别介绍了三次握手.四次挥手.同时打开和同时关闭,TCP连接还有两种场景分别是半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Du ...

随机推荐

  1. PHP二维码生成

    原文链接:http://www.qqdeveloper.com/detail/14/1.html 代码下载地址:链接:http://pan.baidu.com/s/1dFgqiaP 密码:lex5 材 ...

  2. [转]去掉IOS下的input 和textarea的内阴影

    在IOS下,input 和textarea表单默认会有个内阴影,一定程度上影响视觉一致,可通过设置下面代码去掉: input{-webkit-appearance: none;}

  3. Hive(6)-DML数据操作

    一. 数据导入 1. 语法 load data [local] inpath 'path' [overwrite] into table table_name [partition (partcol1 ...

  4. STM32JTAG口用作普通IO的配置

    使用Jlink向STM32烧录程序时,需要使用6个芯片的引脚(以STM32F103C8T6为例),分别是PB4/JNTRST.PB3/JTDO.PA13/JTMS.PA14/JTCK.PA15/JTD ...

  5. 【8086汇编-Day5】第二次实验

    debug的使用 偷个懒,之前写过了这里不再赘述 实验 1)实验1 要求:用e将一些数据写入内存,用a写入一段程序,t 逐条执行 观察具体参数变化,并探究现象 1.e写入,d检查 2.a写入程序 3. ...

  6. MongoDB入门---文档查询操作之条件查询&and查询&or查询

    经过前几天的学习之路,今天终于到了重头戏了.那就是文档查询操作.话不多说哈,直接看下语法: db.collection.find(query, projection) query :可选,使用查询操作 ...

  7. 20145202马超 2016-2017-2《Java程序设计》课程总结

    学号 2016-2017-2<Java程序设计>课程总结 (按顺序)每周作业链接汇总 预备作业1(http://www.cnblogs.com/tuolemi/p/6193756.html ...

  8. hive 中的float和double

    表employees中字段 taxes(税率)用类型float存储 hive> select name, salary, taxes from employees where taxes  &g ...

  9. C# 终本案件、综合执行人、裁判文书爬虫

    终本案件:http://zxgk.court.gov.cn/zhongben/new_index.html 综合执行人:http://zxgk.court.gov.cn/zhixing/new_ind ...

  10. Windows运行机理——窗口和句柄

    Windows运行机理这系列文章都是来至于<零基础学Qt4编程>——吴迪,个人觉得写得很好,所以进行了搬运和个人加工 1. 窗口 窗口是Windows应用程序中一个非常重要的元素,一个Wi ...