link1: http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/html
link2: http://dev.csdn.net/article/84901.shtm服务器
link3: http://lo-res.org/~aaron/tcpipillustrated/richard_stevens_-TCPIP-Illustrated-Vol.1/tcp_keep.htm网络
link1是keepalive的使用手册。link3是richard stevens大做TCPIP illustrated的其中一个章节,专讲keepalive,侧重原理和概念。link2是link3的中文翻译版。想了解keepalive,直接看这几个link就能够了。如下的文字只是我我的的读书笔记。app
首先,须要搞清楚TCP keepalive是干什么用的。从名字理解就可以知道,keepalive就是用来检测一个tcp connection是否还链接正常。当一个tcp connection创建好以后,若是双方都不发送数据的话,tcp协议自己是不会发送其它的任何数据的,也就是说,在一个idle的connection上,两个socket之间不产生任何的数据交换。从另外一个方面讲,当一个connection创建以后,连接双方能够长时间的不发送任何数据,好比几天,几星期甚至几个月,但该connection仍然存在。less
因此,这就可能出现一个问题。举例来讲,server和client创建了一个connection,server负责接收client的request。当connection创建好以后,client因为某种缘由机器停机了。但server端并不知道,因此server就会一直监听着这个connection,但其实这个connection已经失效了。socket
keepalive就是为这样的场景准备的。当把一个socket设置成了keepalive,那么这个socket空闲一段时间后,它就会向对方发送数据来确认对方仍然存在。放在上面的例子中,若是client停机了,那么server所发送的keepalive数据就不会有response,这样server就可以确认client完蛋了(至少从表面上看是这样)。tcp
再继续介绍keepalive以前,还有几点须要说明:ide
首先,keepalive并非惟一的手段。想知道某connection是否失效,除了keepalive还有其它的一些办法,好比heartbeat,或者本身发送检测信息等等。函数
其次,keepalive并非TCP协议的一部分。之因此如此,也是由于:一,不是全部的场景下都须要使用keepalive;二,keepalive有它本身的缺陷,如link2中所列,“在Host Requirements RFC罗列有不使用它的三个理由:(1)在短暂的故障期间,它们可能引发一个良好链接(good connection)被释放(dropped),(2)它们消费了没必要要的宽带,(3)在以数据包计费的互联网上它们(额外)花费金钱。”ui
再次,keepalive没有办法区分出究竟是因为对方的程序意外终止仍是因为网络故障而致使的connection的失效。因此,如前文所述,它可能由于网络的短暂故障而致使一个good connection被释放。
link2和link3中的23.2节描述了在不一样的情形下keepalive的做用。我直接粘贴过来了:
在此描述中,咱们称使用存活选项的那一段为服务器,另外一端为客户端。也能够在客户端设置该选项,且没有不容许这样作的理由,但一般设置在服务器。若是链接两端都须要探测对方是否消失,那么就能够在两端同时设置(好比NFS)。
若在一个给定链接上,两小时以内无任何活动,服务器便向客户端发送一个探测段。(咱们将在下面的例子中看到探测段的样子。)客户端主机必须是下列四种状态之一:
1.客户端主机依旧活跃(up)运行,而且从服务器可到达。从客户端TCP的正常响应,服务器知道对方仍然活跃。服务器的TCP为接下来的两小时复位存活定时器,若是在这两个小时到期以前,链接上发生应用程序的通讯,则定时器从新为往下的两小时复位,而且接着交换数据。
2.客户端已经崩溃,或者已经关闭(down),或者正在重启过程当中。在这两种状况下,它的TCP都不会响应。服务器没有收到对其发出探测的响应,而且在75秒以后超时。服务器将总共发送10个这样的探测,每一个探测75秒。若是没有收到一个响应,它就认为客户端主机已经关闭并终止链接。
3.客户端曾经崩溃,但已经重启。这种状况下,服务器将会收到对其存活探测的响应,但该响应是一个复位,从而引发服务器对链接的终止。
4.客户端主机活跃运行,但从服务器不可到达。这与状态2相似,由于TCP没法区别它们两个。它所能代表的仅是未收到对其探测的回复。
服务器没必要担忧客户端主机被关闭而后重启的状况(这里指的是操做员执行的正常关闭,而不是主机的崩溃)。当系统被操做员关闭时,全部的应用程序进程(也就是客户端进程)都将被终止,客户端TCP会在链接上发送一个FIN。收到这个FIN后,服务器TCP向服务器进程报告一个文件结束,以容许服务器检测这种状态。
在第一种状态下,服务器应用程序不知道存活探测是否发生。凡事都是由TCP层处理的,存活探测对应用程序透明,直到后面2,3,4三种状态发生。在这三种状态下,经过服务器的TCP,返回给服务器应用程序错误信息。(一般服务器向网络发出一个读请求,等待客户端的数据。若是存活特征返回一个错误信息,则将该信息做为读操做的返回值返回给服务器。)在状态2,错误信息相似于“链接超时”。状态3则为“链接被对方复位”。第四种状态看起来像链接超时,或者根据是否收到与该链接相关的ICMP错误信息,而可能返回其它的错误信息。
而在link1中详细介绍了keepalive的使用。这里简单概括一下。
使用keepalive其实很是简单,就是三个参数和一个函数。先说这个函数。默认状况下, socket是不支持keepalive的,因此须要使用setsockopt函数设置一下(话说setsockopt函数其实很好很强大,之后再仔细琢磨一下)。
/* Check the status for the keepalive option */
if(getsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {
perror("getsockopt()");
close(s);
exit(EXIT_FAILURE);
}
像这样就将socket设置成了keepalive。
接着说三个参数。keepalive会使用到系统定义的三个参数: tcp_keepalive_time,tcp_keepalive_intvl,tcp_keepalive_probes。
time是指当一个connection通过了多长时间没有发送packet就开始启动keepalive的检测。系统默认设置为7200秒,就是说,若是某个connection已经7200秒没有发送过数据,那么这时候就要开始发送keepalive的探测包来进行检测了。“the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive, this counter is not used any further “
intvl是指每两个keepalive的探测包之间的时间间隔。系统默认为75秒。“the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime “
probes则是指判断一个connection失效所须要发送的探测包的数量。系统默认为9个。“the number of unacknowledged probes to send before considering the connection dead and notifying the application layer “
这三个参数既能够经过改写系统的默认配置文件来进行设置,也能够经过setsockopt函数来进行设置。具体方法见link1。
因此要使用keepalive,首先设置好以上三个参数,而后经过setsockopt来启动keepalive,这样就OK了
http://blog.csdn.net/historyasamirror/article/details/5526486