简体   繁体   English

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

[英]How does Socket Keep-Alive extension work? C#

While coding Socket client/server, I've thought to implement HeartBeat to know whether client is alive, but then searched for other ways to do so and spotted this piece of code which seems to do exactly that from description: 在编写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);
    }
}

It seems to do the job in a much more simple way than implementing a HeartBeat, although I don't quite understand how it works, seems to be doing something with unmanaged code? 它似乎以比实现HeartBeat更简单的方式完成工作,虽然我不太明白它是如何工作的,似乎是在用非托管代码做些什么? And if so, why? 如果是这样,为什么?

An explanation would be appreciated, thanks! 我们将不胜感激,谢谢!

KeepAlive is part of the TCP protocol. KeepAlive是TCP协议的一部分。 By enabling KeepAlive, the OS will periodically send empty packets to the other party and wait for an ACK. 通过启用KeepAlive,操作系统将定期向另一方发送空数据包并等待ACK。 If no ACK is received within the required timeout period the connection is assumed to be broken and the application can be notified. 如果在所需的超时时间内没有收到ACK,则认为连接已断开,并且可以通知应用程序。

However KeepAlive is usually not required unless you have a receive-only socket or your connection is going to be idle for long periods of time. 但是,除非您有一个只接收套接字或者您的连接将长时间处于空闲状态,否则通常不需要KeepAlive。

In a receive-only socket you don't send any data so the only way to detect a broken connection is send a null packet and wait for the ACK. 在仅接收套接字中,您不发送任何数据,因此检测断开连接的唯一方法是发送空数据包并等待ACK。

If OTOH you have a bidirectional socket, every time you send data to the other party you are essentially also checking if the connection was dropped, so no need for KeepAlive's. 如果OTOH你有一个双向套接字,每次你向对方发送数据时,你基本上也在检查连接是否被丢弃,所以不需要KeepAlive。 Note that if you send data only in response to the other end sending data, then you still need KeepAlive because you may never get to the "sending" part of your protocol. 请注意,如果您仅发送数据以响应另一端发送数据,那么您仍然需要KeepAlive,因为您可能永远无法进入协议的“发送”部分。

Also, as noted by Remy Lebeau in his comment, a connection that can be idle for long periods, may require KeepAlive as some routers/firewalls close idle connections after awhile. 此外,正如Remy Lebeau在评论中指出的那样,可能长时间闲置的连接可能需要KeepAlive,因为一些路由器/防火墙会在一段时间后关闭空闲连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM