12

我正在寻找一种在.NET 中进行保持活动检查的方法。该方案适用于 UDP 和 TCP。

目前在 TCP 中,我所做的是一侧连接,当没有数据要发送时,它每 X 秒发送一次保持活动状态。

我希望对方检查数据,如果在 X 秒内未收到,则引发事件左右。

我尝试做的一种方法是进行阻塞接收并将套接字的 RecieveTimeout 设置为 X 秒。但问题是每当超时发生时,套接字的 Receive 会抛出一个 SocketException 并且这一侧的套接字会关闭,这是正确的行为吗?为什么套接字在超时后关闭/死亡而不是继续?

检查是否有数据和睡眠是不可接受的(因为我可能在睡眠时接收数据滞后)。

那么解决这个问题的最佳方法是什么,为什么我在另一边描述的方法失败了?

4

4 回答 4

19

如果您的字面意思是“KeepAlive”,请尝试以下操作。

    public static void SetTcpKeepAlive(Socket socket, uint keepaliveTime, uint keepaliveInterval)
    {
        /* the native structure
        struct tcp_keepalive {
        ULONG onoff;
        ULONG keepalivetime;
        ULONG keepaliveinterval;
        };
        */

        // marshal the equivalent of the native structure into a byte array
        uint dummy = 0;
        byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
        BitConverter.GetBytes((uint)(keepaliveTime)).CopyTo(inOptionValues, 0);
        BitConverter.GetBytes((uint)keepaliveTime).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
        BitConverter.GetBytes((uint)keepaliveInterval).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);

        // write SIO_VALS to Socket IOControl
        socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
    }

注意时间单位是毫秒。

于 2008-10-05T01:52:12.827 回答
1

According to MSDN, a SocketException thrown when ReceiveTimeout is exceeded in Receive call will not close the socket. There is something else going on in your code.

Check the caught SocketException details - maybe it's not a timeout after all. Maybe the other side of the connection shuts down the socket.

Consider enabling network tracing to diagnose the exact source of your problems: look for "Network Tracing" on MSDN (can't provide you with a link, since right now MSDN is down).

于 2008-10-04T12:59:14.807 回答
1

如果您有一个 tcp 服务器,它只是以不规则的时间间隔写入数据,并且您希望在后台保持活动状态:

tcpClient.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 1);
tcpClient.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, 2);
tcpClient.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveRetryCount, 2);
tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

如果服务器不(通常自动)回复 tcp keep alives,将导致异步读取引发超时异常。

于 2021-10-08T13:54:21.873 回答
0

由于您不能使用阻塞(同步)接收,您将不得不接受异步处理。幸运的是,使用 .NET 很容易做到这一点。查找 BeginReceive() 和 EndReceive() 的描述。或者查看这篇文章这篇文章。

至于超时行为,我没有找到对此的结论性描述。由于没有记录,否则您必须假设它是预期的行为。

于 2008-10-03T22:56:05.243 回答