TCP保持活动频率不一致

我在.NET应用程序中configuration了一个TCP套接字,每15分钟发送一次Keep-Alive数据包。 请注意,在.NET世界中,只能使用底层的Socket.IOControl API来传递代表本地结构的字节,而只能操纵这个参数(而不是简单地启用 Keep-Alives)。

观察下面传出的Keep-Alives的Wireshark捕获:

Wireshark捕获

一切按计划在12:35和14:05之间进行(Keep-Alive每15分钟发送一次),但之后,这些数据包发送的频率开始大幅变化(24分钟,15分钟,29分钟,1小时4分钟)。 除了这种不一致外,应用程序在此期间的行为完全如预期。

在这段时间过后不久,Keep-Alive跨度又恢复到了15分钟。


仅供参考,我写的代码设置参数如下:

 private void SetKeepAlive(uint time, uint interval, SocketOptionLevel level) { // The native structure for this is defined in mstcpip.h as: //struct tcp_keepalive { //u_long onoff; //u_long keepalivetime; //u_long keepaliveinterval; //}; var inValue = new[] { Convert.ToUInt32(true), time, interval } .SelectMany(BitConverter.GetBytes) .ToArray(); var outValue = new byte[sizeof(uint)]; Socket.SetSocketOption(level, SocketOptionName.KeepAlive, true); Socket.IOControl(IOControlCode.KeepAliveValues, inValue, outValue); } 

…等同于:

 SetKeepAlive(900000, 1000, SocketOptionLevel.Socket); 

这些Keep-Alives的目的是为了防止我们的一些networking硬件在超时(大约30分钟)后断开连接,所以我们不能承受这些间隔的巨大变化。 对于我们来说,构build应用程序级别的心跳和其他这样的用户级解决scheme也是一件痛苦的事情,太多的系统需要改变。

什么可能导致这种不一致的行为?

从RFC 1122 第4.2.3.6节 :

只有在间隔内没有收到连接的数据或确认数据包的情况下,才能发送保持连接的数据包。

这意味着,如果您的情况下保持活动的数据包将在您的应用程序发送或接收最后一个数据包15分钟后发送。 如果您的应用程序空闲,它只会每15分钟发送一次。