设置 Keep-Alive 值






4.33/5 (3投票s)
SetKeepAliveValues 方法启用或禁用每个连接的 TCP keep-alive 选项设置,该选项指定 TCP keep-alive 超时和间隔。
评论改编自以下站点
- https://tldp.cn/HOWTO/TCP-Keepalive-HOWTO/index.html
- http://msdn.microsoft.com/en-us/library/dd877220(VS.85).aspx
引言
为了理解 TCP keepalive(我们简称 keepalive)的作用,您只需要阅读名称:保持 TCP 活跃。 这意味着您将能够检查您连接的套接字(也称为 TCP 套接字),并确定连接是否仍然启动并运行,或者是否已断开。
背景
在大多数情况下,了解 TCP keepalive 没有必要,但在特定情况下,它可能非常有用。您需要了解基本的 TCP/IP 网络概念。
什么是 TCP keepalive?
keepalive 的概念非常简单:当您设置 TCP 连接时,您会关联一组计时器。 其中一些计时器处理 keepalive 过程。 当 keepalive 计时器达到零时,您会向您的对等方发送一个没有数据的 keepalive 探测数据包,并且 ACK 标志已打开。 由于 TCP/IP 规范,您可以这样做,作为一种重复的 ACK,并且远程端点不会有任何参数,因为 TCP 是面向流的协议。 另一方面,您将收到来自远程主机的回复(远程主机根本不需要支持 keepalive,只需支持 TCP/IP),没有数据且设置了 ACK。
如果您收到对 keepalive 探测的回复,您可以断言连接仍然启动并运行,而无需担心用户级实现。 事实上,TCP 允许您处理流,而不是数据包,因此零长度的数据包对于用户程序来说并不危险。
此过程非常有用,因为如果其他对等方失去连接(例如通过重新启动),即使您没有流量,您也会注意到连接已断开。 如果您的对等方未回复 keepalive 探测,您可以断言该连接不能被认为是有效的,然后采取正确的操作。
Using the Code
SetKeepAliveValues
方法启用或禁用 TCP keep-alive 选项的每个连接设置,该选项指定用于 TCP keep-alive 数据包的 TCP keep-alive 超时和间隔。 有关 keep-alive 选项的更多信息,请参见 RFC 1122 中指定的互联网主机通信层要求的 4.2.3.6 节,该节可在 IETF 网站上找到。
传递给 Socket.IOControl
的 optionInValue
参数应指向 Mstcpip.h 头文件中定义的 tcp_keepalive
结构。 该结构定义如下
/* Argument structure for SIO_KEEPALIVE_VALS */
struct tcp_keepalive {
u_long onoff;
u_long keepalivetime;
u_long keepaliveinterval;
};
将 tcp_keepalive
C struct
转换为 C# struct
。
// Convert tcp_keepalive C struct To C# struct
[
System.Runtime.InteropServices.StructLayout
(
System.Runtime.InteropServices.LayoutKind.Explicit
)
]
unsafe struct TcpKeepAlive
{
[System.Runtime.InteropServices.FieldOffset(0)]
[
System.Runtime.InteropServices.MarshalAs
(
System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst = 12
)
]
public fixed byte Bytes[12];
[System.Runtime.InteropServices.FieldOffset(0)]
public uint On_Off;
[System.Runtime.InteropServices.FieldOffset(4)]
public uint KeepaLiveTime;
[System.Runtime.InteropServices.FieldOffset(8)]
public uint KeepaLiveInterval;
}
public int SetKeepAliveValues
(
System.Net.Sockets.Socket Socket,
bool On_Off,
uint KeepaLiveTime,
uint KeepaLiveInterval
)
{
int Result = -1;
unsafe
{
TcpKeepAlive KeepAliveValues = new TcpKeepAlive();
KeepAliveValues.On_Off = Convert.ToUInt32(On_Off);
KeepAliveValues.KeepaLiveTime = KeepaLiveTime;
KeepAliveValues.KeepaLiveInterval = KeepaLiveInterval;
byte[] InValue = new byte[12];
for (int I = 0; I < 12; I++)
InValue[I] = KeepAliveValues.Bytes[I];
Result = Socket.IOControl(IOControlCode.KeepAliveValues, InValue, null);
}
return Result;
}
调用方法
System.Net.Sockets.Socket Socket = new System.Net.Sockets.Socket
(
System.Net.Sockets.AddressFamily.InterNetwork,
System.Net.Sockets.SocketType.Stream,
System.Net.Sockets.ProtocolType.Tcp
);
// Set 10 Hours: 10 * 60 * 60 * 1000 = 36,000,000 every 1 Second 1000
SetKeepAliveValues(Socket, true, 36000000, 1000);
历史
- 2010 年 10 月 12 日:首次发布