您的位置:首页 > 理论基础 > 计算机网络

Linux操作系统下TCP keepalive属性查看

2013-09-26 15:10 323 查看
Tcp是面向连接的,在实际应用中通常都需要检测连接是否还可用.如果不可用,可分为:
a. 连接的对端正常关闭.
b. 连接的对端非正常关闭,这包括对端设备掉电,程序崩溃,网络被中断等.这种情况是不能也无法通知对端的,所以连接会一直存在,浪费国家的资源.
tcp协议栈有个keepalive的属性,可以主动探测socket是否可用,不过这个属性的默认值很大.
全局设置可更改/etc/sysctl.conf,加上:
net.ipv4.tcp_keepalive_intvl = 20

net.ipv4.tcp_keepalive_probes = 3

net.ipv4.tcp_keepalive_time = 60
在程序中设置如下:
int keepAlive = 1; // 开启keepalive属性

int keepIdle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测

int keepInterval = 5; // 探测时发包的时间间隔为5 秒

int keepCount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.
setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));

setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));

setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));

setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
在程序中表现为,当tcp检测到对端socket不再可用时(不能发出探测包,或探测包没有收到ACK的响应包),select会返回socket可读,并且在recv时返回-1,同时置上errno为ETIMEDOUT。

Linux检测TCP连接断开的一种简单实现方法:http://hi.baidu.com/gthinking/blog/item/3d880ed8ac10623633fa1cd0.html
问题:Linux中开一个TCP套节字(客户端),不断读取对端(服务器)的数据,如果对端没有数据可读,认为是正常,如果对端非法关闭端口(死机、进程死掉、网线断掉等等)则重新连接对端。
解析:Linux中似乎没有即时检测到连接断开的函数或者信号,所以基本不要指望操作系统马上告诉你对方已经断开连接了。一般可以采取业务层的心跳检测,超时没有收到心跳包,就认为是对端已经断开,还有些更高级的方法比如KeepAlive,脑子笨,学不会,但都不外乎互相定时发点校验信息。
我要说的解法:肯定不是什么高明的技术,搜搜网上的帖子,再根据自己的经验,就出来了。
第一步,select函数的返回值判断。在年ucLinux,EM8511平台下跑,select没有数据时返回的是-1,有数据返回的就是大于0的整数,好像还没有碰到过0的时候。 千万不要以为返回-1就是错误。
小提示:select函数调用之后会将清空delay中的值(清成0),如果是反复调用select并希望有一定延时的话,一定要记得每次调用前都要指定延时参数。
第二步,检测到select是1,说明你的对端有可能是关闭了,千万不要高高兴兴不顾一切地就去读数据。实际上这个时候由于断开之后TCP/IP本身的一些握手信号,select会认为socket中有数据。这个使用如果使用read去读,将会返回0。这时select和read的结果明显是不一致的,我们认为是对端端口断开。
用这个方法检测,未必是完全之策,但是在我的程序上用起来还是很爽的。

Reference:
http://www.linux.org/docs/ldp/howto/TCP-Keepalive-HOWTO/programming.html
TCP保活定时器http://www.cublog.cn/u3/105349/showart_2216959.html
Linux中select函数学习及实例笔记http://blog.chinaunix.net/u3/104447/showart_2150356.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: