在solaris上进行跨平台编译的时候,如下几个和tcp相关的变量未能够正确找到定义,导致报错:tcp_keepidle、tcp_keepintvl、tcp_keepcnt。
一、描述
这几个变量均为用来设置tcpkeepalive选项的参数,相关功能描述如下:
tcp_keepidle:在双方连接的socket链路上均没有数据交互时,发送保活探测分节的间隔时间;
tcp_keepintvl:发送两次保活探测分节的间隔时间;
tcp_keepcnt:探测重试的次数
二、keepalive的原因
双方已建立连接的情况,如果某端非正常断开,另一端是无法检测到的,这样会导致socket资源的浪费。
三、keepalive信息的查看
unix:
缺省值:7200000 毫秒
建议值:15000 毫秒
# ndd -get /dev/tcp tcp_keepalive_interval
7200000
# ndd -set /dev/tcp tcp_keepalive_interval 300000
linux:
sudo sysctl -a | grep keepalive
四、keepalive的方案
给一个TCP套接字设置保持存活选项。如果keepalivetime小时内在该套接字的任意方向都没有数据的交换,则TCP就自动给对端发送一个保持存活探测分节(keep-alive probe)。这是一个对端必须响应的TCP分节,导致三种情况
对端以期望的TCP分节。应用进程没有任何反应(因为正常,所以默认没有反应)。又经过keepalivetime小时后,TCP将发送另一个探测分节,一直持续
对端以RST响应,它告知TCP:对端已经崩溃且已经重新启动。该套接字的待处理错误被设置为ECONNRESET,套接字本身则被关闭。
对端对保持存活探测分节没有任何响应。重新发送探测分节,尝试几次之后若在某规定时间内一直无对端的响应,则放弃。该套接字的待处理错误就被设置为ETIMEOUT,套接字本身被关闭。
此选项的功用是检测对端主机是否崩溃或变得不可达。如果对端进程崩溃,它的tcp将跨连接发送一个FIN,这可以通过select很容易检测到
使用方法:(类UNIX中)
在代码里针对每个socket进行单独设定, 使用起来灵活.
除了keepAlive 开关, 还有keepIdle, keepInterval, keepCount 3个属性, 使用简单, 如下:
[cpp] view plain copy
-
int keepAlive = 1; // 开启keepalive属性. 缺省值: 0(关闭)
-
int keepIdle = 60; // 如果在60秒内没有任何数据交互,则进行探测. 缺省值:7200(s)
-
int keepInterval = 5; // 探测时发探测包的时间间隔为5秒. 缺省值:75(s)
-
int keepCount = 2; // 探测重试的次数. 全部超时则认定连接失效..缺省值:9(次)
-
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));
-
setsockopt(s, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
-
setsockopt(s, SOL_TCP, TCP_KEEPINTVL, (void*)&keepInterval, sizeof(keepInterval));
-
setsockopt(s, SOL_TCP, TCP_KEEPCNT, (void*)&keepCount, sizeof(keepCount));
使用时需要#include <netinet/tcp.h>, 否则SOL_TCP和TCP_KEEPIDLE等3个宏找不到.