我在一个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参数实际上是以分钟为单位的吗,与某些文档相反?在代码中是否有某个函数可能会影响此超时参数?
发布于 2013-03-07 02:46:01
我可以通过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应用程序指示连接在大约4秒内被丢弃(我假设等待时间为3秒,保持连接空闲时间为1秒)。
我还可以在代码中的单个套接字级别上更改此设置。在文件/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));将具有与更改系统参数相同的效果。
我确实同意其他答案,即应用程序级别的keepalives确实是可行的。而且,正如前面提到的here,
TCPRFC1122,第4.2.3.6节指出,路由器可能无法可靠地传输对没有数据的
keepalives的确认;这可能会导致有效连接丢失。此外,TCP/IP协议栈根本不需要支持keepalives (许多嵌入式协议栈也不需要),因此此解决方案可能不适用于其他平台。
但是,在非测试环境中,我不能访问TCP输入,在TCP输入中我可以实现应用程序级keepalives的另一端,因此TCP keepalives可能是我惟一的选择。
发布于 2013-03-06 02:50:06
最好的选择是应用程序层保持活动状态;也就是说,每X秒发送一次无操作(NOP)消息,并期望得到相当快的NOP确认(NOP-ACK)。此外,如果您的远程连接关闭是“优雅的”,那么您的send应该几乎立即解除阻塞。如果它不正常(例如,网络元素发生故障),那么您的应用层保持活动将在您的下一次X+(预期响应时间)时检测到丢失...
发布于 2013-03-06 02:59:45
TCP_KEEPCNT (从Linux2.4开始)在断开连接之前TCP应发送的保持连接探测的最大数目。此选项不应在旨在可移植的代码中使用。
也许这就是原因。你可以在你的应用程序中实现你自己的keep alive,这应该很简单。如果没有应用程序数据或保持活动状态的“心跳”,就开始戳另一端。
https://stackoverflow.com/questions/15230922
复制相似问题