gpt4 book ai didi

c# - Socket Keep-Alive 扩展如何工作? C#

转载 作者:可可西里 更新时间:2023-11-01 02:33:57 24 4
gpt4 key购买 nike

在编写 Socket 客户端/服务器代码时,我曾想过实现 HeartBeat 来了解客户端是否还活着,但后来搜索了其他方法,并发现了这段代码,从描述来看,它似乎就是这样做的:

public static class SocketExtensions
{
/// <summary>
/// A structure used by SetKeepAliveEx Method
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct TcpKeepAlive
{
internal uint onoff;
internal uint keepalivetime;
internal uint keepaliveinterval;
};

/// <summary>
/// Sets the Keep-Alive values for the current tcp connection
/// </summary>
/// <param name="socket">Current socket instance</param>
/// <param name="keepAliveInterval">Specifies how often TCP repeats keep-alive transmissions when no response is received. TCP sends keep-alive transmissions to verify that idle connections are still active. This prevents TCP from inadvertently disconnecting active lines.</param>
/// <param name="keepAliveTime">Specifies how often TCP sends keep-alive transmissions. TCP sends keep-alive transmissions to verify that an idle connection is still active. This entry is used when the remote system is responding to TCP. Otherwise, the interval between transmissions is determined by the value of the keepAliveInterval entry.</param>
public static void SetKeepAliveEx(this Socket socket, uint keepAliveInterval, uint keepAliveTime)
{
var keepAlive = new TcpKeepAlive
{
onoff = 1,
keepaliveinterval = keepAliveInterval,
keepalivetime = keepAliveTime
};
int size = Marshal.SizeOf(keepAlive);
IntPtr keepAlivePtr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(keepAlive, keepAlivePtr, true);
var buffer = new byte[size];
Marshal.Copy(keepAlivePtr, buffer, 0, size);
Marshal.FreeHGlobal(keepAlivePtr);
socket.IOControl(IOControlCode.KeepAliveValues, buffer, null);
}
}

它似乎以一种比实现 HeartBeat 更简单的方式完成这项工作,虽然我不太明白它是如何工作的,但似乎是在用非托管代码做一些事情?如果是这样,为什么?

如有解释,将不胜感激!

最佳答案

KeepAlive 是 TCP 协议(protocol)的一部分。通过启用KeepAlive,操作系统会定期向对方发送空包并等待ACK。如果在要求的超时期限内没有收到 ACK,则假定连接已断开,并且可以通知应用程序。

但是,通常不需要 KeepAlive,除非您有一个只接收套接字或您的连接将长时间空闲。

在只接收套接字中,您不发送任何数据,因此检测断开连接的唯一方法是发送空数据包并等待 ACK。

如果 OTOH 你有一个双向套接字,每次你向另一方发送数据时,你实际上也在检查连接是否已断开,因此不需要 KeepAlive。请注意,如果您发送数据只是为了响应另一端发送数据,那么您仍然需要 KeepAlive,因为您可能永远无法到达协议(protocol)的“发送”部分。

此外,正如 Remy Lebeau 在他的评论中指出的那样,一个可以长时间空闲的连接可能需要 KeepAlive,因为一些路由器/防火墙会在一段时间后关闭空闲连接。

关于c# - Socket Keep-Alive 扩展如何工作? C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37481852/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com