2013-03-05 82 views
2

我在通过下面的代码写入TCP端口的C++应用程序中实现Keepalive时间。没有显示,但我确实检查了有效的退货状态,以验证设置选项是否有效。Keepalive时间 - 在C++中不能减少到一分钟以下

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参数是以秒为单位的,而不是分钟。但是我无法在1分钟之内检测到丢失的连接。

我也试过改变系统变量keepalive讨论在tldp.org讨论,但无济于事。

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

选项是一个int不INT32 – QuentinUK 2013-03-05 18:13:52

+0

@QuentinUK,他们在我的代码相同。尽管如此,编辑清晰。 – Chance 2013-03-05 18:22:01

+0

您是否尝试过实际检查'setsockopt()'的返回码? – 2013-03-05 18:32:26

回答

0

我可以通过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为保持活动空闲)。

我也可以改变这个在代码中的个别插座的水平。在文件/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)); 

将具有不同的系统参数相同的影响。

我不与该应用程序级别的保持连接其他的答案一致是真的要走的路。并且,如所提到here

RFC 1122,节4.2.3.6表示没有数据为TCP 保活确认可能不能够可靠地由路由器发送的; 这可能会导致有效的连接被丢弃。此外,不需要TCP/IP堆栈 支持保活在所有(和许多 嵌入式堆栈没有),所以这种解决方案可能无法转化为其他 平台。

然而,在非测试环境,我没有访问中,我可以实现应用程序级别的保持活动的另一侧的TCP输入,所以TCP持久连接可能是我唯一的选择。

1

最好的办法是应用层保持活跃;即每X秒发送一次无操作(NOP)消息,并期望合理快速的NOP确认(NOP-ACK)。另外,如果您的远程连接关闭是“优雅”,那么您的send应该立即解除封锁。如果不是优美(如网元失败),那么你的应用层保持活动会检测你的下一次X +(预期的响应时间)的损失......

+0

任何一种应用层保持活动的TCP是会出现问题的,最终,它难以适应RTT,抖动,暂时的连接丢失......。有2个时间关键层总是一个坏主意(因此隧道几乎总是使用UDP)。除此之外,您还将在一个流中混合使用应用程序和Keepalive数据,这非常容易出错。 – KillianDS 2013-03-05 19:03:49

+0

当您的保持时间大约为几秒时,RTT和抖动可以忽略不计。如果TCP层不处理暂时的连接丢失,那么你的应用程序必须处理这个问题。我会同意,如果时间紧迫,TCP-acks强加的所有额外流量都会浪费,UDP是更好的选择。 – mark 2013-03-05 19:15:33

+0

问题是,我真的没有访问另一端(另一个进程侦听)。我在测试环境中做,但我不会一直。但是,是的,我同意,应用程序级保活将是我的首选方式。 – Chance 2013-03-05 19:26:00

1

TCP_KEEPCNT(因为Linux 2.4) TCP在丢弃连接之前应该发送的最大Keepalive探测数量。这个选项不应该用在可移植的代码中。

也许这可能是原因。你可以在你的应用程序中实现自己的活着,它应该很容易。如果没有应用数据或保持活力的“心跳”来到,就开始捅另一端。