查看: 6618|回复: 12

TCP keepAlive 详解

[复制链接]
发表于 2011-1-14 10:10:05 | 显示全部楼层 |阅读模式
在一个正常的TCP连接上,当我们用无限等待的方式调用下面的Recv或Send的时候:

   ret=recv(s,&buf[idx],nLeft,flags);

   或

   ret=send(s,&buf[idx],nLeft,flags);

   如果TCP连接被对方正常关闭,也就是说,对方是正确地调用了closesocket(s)或者shutdown(s)的话,

那么上面的Recv或Send调用就能马上返回,并且报错。这是由于closesocket(s)或者shutdown(s)有

个正常的关闭过程,会告诉对方“TCP连接已经关闭,你不需要再发送或者接受消息了”。但是,如果是

网线突然被拔掉,TCP连接的任何一端的机器突然断电或重启动,那么这时候正在执行Recv或Send操作

的一方就会因为没有任何连接中断的通知而一直等待下去,也就是会被长时间卡住。这种情形解决的办法

是启动TCP编程里的keepAlive机制。

    struct TCP_KEEPALIVE inKeepAlive = {0};
    unsigned long ulInLen = sizeof(struct TCP_KEEPALIVE);
    struct TCP_KEEPALIVE outKeepAlive = {0};
    unsigned long ulOutLen = sizeof(struct TCP_KEEPALIVE);
    unsigned long ulBytesReturn = 0;

    inKeepAlive.onoff=1;
    inKeepAlive.keepaliveinterval=5000; //单位为毫秒
    inKeepAlive.keepalivetime=1000;      //单位为毫秒
    ret=WSAIoctl(s, SIO_KEEPALIVE_VALS, (LPVOID)&inKeepAlive, ulInLen,

                          (LPVOID)&outKeepAlive, ulOutLen, &ulBytesReturn, NULL, NULL);

   此处的keepalivetime表示的是TCP连接处于畅通时候的探测频率,一旦探测包没有返回,就以keepaliveinterval

的频率发送,经过若干次的重试,如果探测包都没有返回,那么就得出结论:TCP连接已经断开,于是上面

的Recv或Send调用也就能马上返回,不会无限制地卡住了。

无标题.jpg

上图是对上面文字的说明。亮条之前,TCP处于畅通状态,KeepAlive是以1000毫秒(keepalivetime的值)的频率发送探测包,

在发送到第32个探测包的时候,探测包没有返回,于是就以5000毫秒(keepalivetime的值)的频率发送探测包,重发几次后,

探测包都没有返回,于是就得出结论:此TCP连接已经断开了!

对于Win2K/XP/2003,可以从下面的注册表项找到影响整个系统所有连接的keepalive参数:


[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]

“KeepAliveTime”=dword:006ddd00
“KeepAliveInterval”=dword:000003e8
“MaxDataRetries”=”5″

  对于实用程序来说,2小时的空闲时间太长。因此,我们需要手工开启Keepalive功能并设置合理的Keepalive参数。在XP和

WIN2003系统上,可以针对单独的socket来设置,但是在windows 2000,不能单独设置,如果设置,那么影响是整个系统的

所有socket。

评分

1

查看全部评分

回复

使用道具 举报

发表于 2011-1-14 11:06:02 | 显示全部楼层
三颗油
回复

使用道具 举报

发表于 2011-1-14 12:52:44 | 显示全部楼层
嗯。之前一款网络安全设备,运行一段时间之后,就必须重启,否则无法转发数据。
后来netstat -an,查看有大量的TIME_WAIT。
也就是这些大量的半连接导致了,系统崩溃。
回复

使用道具 举报

发表于 2011-1-16 23:03:46 | 显示全部楼层
路过,学习的
回复

使用道具 举报

发表于 2011-3-30 20:43:35 | 显示全部楼层
本帖最后由 iamstrong 于 2011-5-1 10:43 编辑

调用下面的Recv或Send.
我试了几次。都不行的。
回复

使用道具 举报

发表于 2011-6-6 14:57:42 | 显示全部楼层
和她聊了一晚后感觉豁然开朗,心中块垒都变浮云了。千言万语说出来,不要猜,很累的
回复

使用道具 举报

发表于 2011-6-10 02:49:32 | 显示全部楼层
三克油
回复

使用道具 举报

 楼主| 发表于 2011-6-28 14:16:04 | 显示全部楼层
嗯。之前一款网络安全设备,运行一段时间之后,就必须重启,否则无法转发数据。
后来netstat -an,查看有大量的TIME_WAIT。
也就是这些大量的半连接导致了,系统崩溃。
long_323 发表于 2011-1-14 12:52


谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | CSNA会员注册

本版积分规则

快速回复 返回顶部 返回列表