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

时间:2016-05-27 11:04:24

标签: c# sockets tcp

在编写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更简单的方式完成工作,虽然我不太了解它是如何工作的,似乎是在使用非托管代码?如果是这样,为什么?

感谢您的解释,谢谢!

1 个答案:

答案 0 :(得分:2)

KeepAlive是TCP协议的一部分。通过启用KeepAlive,操作系统将定期向另一方发送空数据包并等待ACK。如果在所需的超时时间内没有收到ACK,则认为连接已断开,并且可以通知应用程序。

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

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

如果OTOH你有一个双向套接字,每次你向对方发送数据时,你基本上也在检查连接是否被丢弃,所以不需要KeepAlive。请注意,如果您仅发送数据以响应另一端发送数据,那么您仍然需要KeepAlive,因为您可能永远无法进入&#34;发送&#34;你的协议的一部分。

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