我在C ++应用程序中实现了一个keepalive时间,该应用程序通过以下代码写入TCP端口。它没有显示,但我实际上检查了有效的返回状态,以验证设置选项是否有效。
int option = 1;
int keepalive_intvl = 1;
int keepalive_count = 1;
int keepalive_idle = 1;
setsockopt(the_socket, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof (int) );
setsockopt(the_socket, SOL_TCP, TCP_KEEPINTVL, &keepalive_intvl, sizeof(int));
setsockopt(the_socket, SOL_TCP, TCP_KEEPCNT, &keepalive_count, sizeof(int));
setsockopt(the_socket, SOL_TCP, TCP_KEEPIDLE, &keepalive_idle, sizeof(int));
我的应用程序正在写入TCP端口,并尝试每秒写入几次。
// write null packet to determine if connection is still good
return ( send( GetDescriptor(),(char*)NULL, 0, 0 ) != -1 );
每当我关闭另一个输入连接时,根据上面的测试,我的应用程序需要一分钟报告连接已关闭。如果我有一个SIGPIPE
处理函数,那么它也需要一分钟的时间来调用它。
我看到的每个文档都表明keepalive参数以秒为单位,而不是几分钟。但我无法在一分钟内检测到丢失的连接。
我也尝试更改与tldp.org讨论的keepalive相关的系统变量,但无济于事。
echo 1 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 1 > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo 1 > /proc/sys/net/ipv4/tcp_keepalive_probes
此行为是否受另一个系统参数控制?与某些文档相反,keepalive参数实际上是几分钟吗?我应该在代码中查找可能影响此超时参数的某个函数吗?
答案 0 :(得分:1)
你最好的选择是应用层保持活着;也就是说,每X秒发送一次无操作(NOP)消息,并期望合理快速的NOP确认(NOP-ACK)。此外,如果您的远程连接关闭是“优雅”,那么您的send
几乎应立即取消阻止。如果它不优雅(例如网络元素失败),那么你的应用层keep-alive将在你下次X +(预期响应时间)时检测到丢失......
答案 1 :(得分:1)
TCP_KEEPCNT(自Linux 2.4起) 丢弃连接之前TCP应发送的最大keepalive探测数。此选项不应用于可移植的代码中。
也许这可能就是原因。你可以在你的应用程序中实现自己的活着,它应该很容易。如果没有应用程序数据或保持活跃的“心跳”,就开始戳另一端。
答案 2 :(得分:1)
我可以通过TCP_LINGER2
值更改整体保持活动时间。
每当我关闭输入tcp进程时,我使用netstat -an
来获取以下行。
tcp 1 0 127.0.0.1:32962 127.0.0.1:7780 CLOSE_WAIT
tcp 0 0 127.0.0.1:7780 127.0.0.1:32962 FIN_WAIT2
我可以用两种不同的方式改变这个FIN_WAIT2
时间。
在系统级别,根据此link,我可以通过修改系统文件来更改它,如下所示:
% cat /proc/sys/net/ipv4/tcp_fin_timeout
60
[To change this to 3 seconds]
# echo "3" > /proc/sys/net/ipv4/tcp_fin_timeout
我的输出TCP应用程序表明连接在大约四秒内被丢弃(我想3等待时间,1为keepalive空闲)。
我也可以在代码中的单个套接字级别更改它。在文件/usr/include/netinet/tcp.h
中,我看到以下内容
#define TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */
所以,在我的代码中添加以下内容,
int wait_time = 3;
setsockopt(the_socket, SOL_TCP, TCP_LINGER2, &wait_time,sizeof(int));
与改变系统参数具有相同的效果。
我同意其他答案,因为应用程序级别的Keepalive真的是要走的路。并且,如上所述here,
RFC 1122,第4.2.3.6节指出TCP的确认 没有数据的Keepalive可能无法被路由器可靠地传输; 这可能会导致有效连接被丢弃。此外,TCP / IP 堆栈不需要支持keepalive(和许多 嵌入式堆栈没有),所以这个解决方案可能无法转换为其他 平台。
但是,在非测试环境中,我无法访问可以实现应用程序级别Keepalive另一端的TCP输入,因此TCP keepalive可能是我唯一的选择。