【发布时间】:2014-10-25 12:02:35
【问题描述】:
我在 .NET 应用程序中配置了一个 TCP 套接字,以每 15 分钟发送一次 Keep-Alive 数据包。请注意,在 .NET 世界中,只能使用低级 Socket.IOControl API 来操作此参数(而不是简单地启用 Keep-Alives)以传入表示本机结构的字节。
观察以下传出 Keep-Alives 的 Wireshark 捕获:
在 12:35 到 14:05 之间一切都按计划进行(每 15 分钟发送一次 Keep-Alives),但在那之后,发送这些数据包的频率开始发生巨大变化(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 的目的是防止我们的某些网络硬件在超时(大约 30 分钟)后断开连接,因此我们无法承受这些间隔变化如此之大。构建应用程序级心跳和其他此类用户级解决方案对我们来说也有点痛苦 - 需要更改的系统太多。
什么可能导致这种不一致的行为?
【问题讨论】:
-
连接一直处于空闲状态吗? keep-alive 的用途是定期交换数据包。如果这已经通过交换应用程序数据实现,则不会发送保持活动状态,即每当交换应用程序数据时都会重置计时器。
-
如果在此期间发送了常规数据报,是否会抑制保活(即计时器被重置)?这在逻辑上是有道理的,但我的印象(不记得为什么)事实并非如此。
-
是的,keep-alives 只是用来填补空闲时间。如果没有空闲的东西,那么就不需要保持活力。 TCP 是一个非常智能的协议 :)
-
谢谢,史蒂芬。你有这方面的文档吗?这确实完全有道理,但我在网上阅读的少数资源在这一点上是模棱两可的。我认为这种“优化”将取决于实现,而不是标准规定的。
-
我已将详细信息放入答案中。
标签: .net windows sockets tcp wireshark