目前手头有个关于心博功能的一个案例, 在使用SOL_SOCKET, SO_KEEPALIVE上有一点心得,想写出来和大家分享一下。
关于SOL_SOCKET选项SO_KEEPALIVE有一个很详细的英文How TO, 在下面的网页中大家可以看到详细的内容
[url=http://www.icewalkers.com/Linux/Howto/TCP-Keepalive-HOWTO/index.html]http://www.icewalkers.com/Linux/Howto/TCP-Keepalive-HOWTO/index.html[/url]
在《UNIX网络编程第1卷》中也有详细的阐述:
SO_KEEPALIVE
保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自
动给对方 发一个保持存活探测分节(keepalive
probe)。这是一个对方必须响应的TCP分节.它会导致以下三种情况:对方接收一切正常:以期望的ACK响应。2小时后,TCP将发出另一个探测分
节。对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接
口本身则被关闭。对方无任何响应:源自berkeley的TCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟
15秒后若仍无响应就放弃。套接口的待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是“host
unreachable(主机不可达)”,说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为 EHOSTUNREACH。
在该书的第158页有更详细的描述。
根据上面的介绍我们可以知道对端以一种非优雅的方式断开连接的时候,我们可以设置SO_KEEPALIVE属性使得我们在2小时以后发现对方的TCP连接是否依然存在。
keepAlive = 1;
Setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));
如果我们不能接受如此之长的等待时间,从TCP-Keepalive-HOWTO上可以知道一共有两种方式可以设置,一种是修改内核关于网络方面的
配置参数,另外一种就是SOL_TCP字段的TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT三个选项。
The tcp_keepidle parameter specifies the interval of inactivity
that causes TCP to generate a KEEPALIVE transmission for an application
that requests them. tcp_keepidle defaults to 14400 (two hours).
/*开始首次KeepAlive探测前的TCP空闭时间 */
The tcp_keepintvl parameter specifies the interval between the nine
retries that are attempted if a KEEPALIVE transmission is not
acknowledged. tcp_keepintvl defaults to 150 (75 seconds).
/* 两次KeepAlive探测间的时间间隔*/
The TCP_KEEPCNT option specifies the maximum number of keepalive
probes to be sent. The value of TCP_KEEPCNT is an integer value between
1 and n, where n is the value of the systemwide tcp_keepcnt parameter.
/* 判定断开前的KeepAlive探测次数 */
因此我们可以得到
int keepIdle = 6;
int keepInterval = 5;
int keepCount = 3;
Setsockopt(listenfd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle));
Setsockopt(listenfd, SOL_TCP,TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
Setsockopt(listenfd,SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
我们需要注意的TCP-Keepalive-HOWTO上这段话:
Remember that keepalive is not program−related, but socket−related,
so if you have multiple sockets, you can handle keepalive for each of
them separately.
这些属性是sockt继承的,非整个代码内的所有sockets都继承这个属性,因为如果要应用到多个套接口上必须分别使用Setsockopt, Setsockopt是setsockopt的包裹函数。
如果心搏函数要维护客户端的存活,即服务器必须每隔一段时间必须向客户段发送一定的数据,那么使用SO_KEEPALIVE是有很大的不足的。因为
SO_KEEPALIVE选项指"此套接口的任一方向都没有数据交换",我不知道大家是怎么理解这个实现的。在Linux
2.6系列上,上面话的理解是只要打开SO_KEEPALIVE选项的套接口端检测到数据发送或者数据接受就认为是数据交换。
因此在这种情况下使用 SO_KEEPALIVE选项 检测对方是否非正常连接是完全没有作用的,在每隔一段时间发包的情况,
keep-alive的包是不可能被发送的。上层程序在非正常端开的情况下是可以正常发送包到缓冲区的。非正常端开的情况是指服务器没有收到"FIN"
或者 "RST"包。
当然这种情况也是比较好断定对方是否存活,我提出来的主要原因是想看看大家对"此套接口的任一方向都没有数据交换"是怎么去理解的。
分享到:
相关推荐
Echo service using TCP sockets between two systems with socket options SO_REUSEADDR, SO_KEEPALIVE, TCP_NODELAY and SO_LINGER
设置好keepalive以后,我们通过实验来看看当client异常退出或是网络断掉的情况下,keepalive怎么通知我们异常断开的情况。这里采用select模式,实验环境为XP系统和Win7系统,几种情况返回值如下: 1. 正常断开 ...
nginx upstream 连接池 ngx_http_upstream_keepalive-d9ac9ad67f45.tar.gz
这是关于WinSock_TCP_keepalive内容的知识。 通信机制中,对方是否断开,有两种判断方法。 一种就是使用心跳包,另一种就是使用KEEPALIVE.这就是关于keepalive的介绍资料
tcp_keepalive_time:表示的是近一次数据包(简单的不含数据的ACKs包)发送与第一次keepalive探针发送之间的时间间隔;当连接被标记为keepalive之后,这个计数器不会再使用。 tcp_keepalive_intvl:表示的是...
Linux平台下的看门狗驱动,在8180下运行良好,移植方便
TCP keepalive:TCP keepalive:参考于RFC1122 TCP内建的option,由c socket或kernel设置参数: TCP_KEEPCNT - tcp_keepalive_probes (重试几次决定断线) TCP_KEEPINTVL - tcp_keepalive_intvl(ACK传了多久没回应要重试)...
nginx第三方插件,用于连接mysql数据库,提升nginx连接mysql的性能,
:link: 净keepalive 使用模块的Node缺少的( TCP_KEEPINTVL和TCP_KEEPCNT ) SO_KEEPALIVE套接字选项设置程序和获取程序。 经过测试 :penguin: linux & :green_apple: osx ( amd64和arm64都应该) :smiling_face_...
那什么是keepalive?作用是什么?...sk->keepalive_time 探测的心跳间隔,TCP链接在多少秒之后没有数据报文传输启动探测报文 sk->keepalive_intvl 探测间隔,未收到回复时,重试的时间间隔 默认配置查看
问题描述:在Linux系统中高并发的Squid服务器,TCP TIME_WAIT套接字数量经常达到两、三万,服务器很容易被拖死。解决方法:通过修改Linux内核参数,可以减少linux服务器...vi /etc/sysctl.conf增加以下几行: 代码如下:...
在ARM+LINX下,传统看门狗存在的问题及解决方案
nginx tcp lua 模块 一个对 nginx 有 lua 支持的 tcp 模块。 大多数代码是从 ngx-lua-module 复制而来的,并且指令/常量/APIs 计划与 ngx-lua ... lua_socket_keepalive_timeout lua_socket_connect_timeout lua_s
考虑这个问题的方法是,如果在 TCP 套接字上将SO_KEEPALIVE设置为1 ,那么当套接字在TCP_KEEPIDLE秒内没有收到任何数据时,系统会发送一个 keepalive 探测。 如果TCP_KEEPINTVL秒过去了,系统会发送另一个探测
在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE.系统默认是设置的2小时的心跳频率.但是它检查不到机器断电.网线拔出.防火墙这些断线.而且逻辑层处理断线可能也不是那么好处理.一般,如果...
如果在keepalive_time时间内双方没有任何的数据包传输,则开启keepalive功能的一端将发送 eepalive数据包,若没有收到应答,则每隔keepalive_intvl时间再发送该数据包,发送keepalive_probes次。一直没有 收到应答,...
libssh2的最新版本1.4.2,bsd的license
zookeeper3.4_haproxy1.7_keepalive 结对好用
springboot keepalive 服务端,客户端测试
* @see ap_conn_keepalive_e *) keepalive: ap_conn_keepalive_e; flags2: Cardinal; { The following are in the flags bitset: (** have we done double-reverse DNS? -1 yes/failure, 0 not yet, * 1 yes/...