检测意外的插座断开连接

时间:2012-07-05 08:13:44

标签: c# sockets

这不是关于如何做到这一点的问题,而是一个关于我做错的问题。我已经读过,在等待数据(BeginReceive)时,无法检测套接字是否意外关闭(如杀死服务器/客户端进程,拉动网络电缆),而不使用定时器或定期发送消息等等。但是很长一段时间我一直在使用以下设置来做到这一点,到目前为止它一直都很完美。

public void OnReceive(IAsyncResult result)
{
    try
    {
        var bytesReceived = this.Socket.EndReceive(result);

        if (bytesReceived <= 0)
        {
            // normal disconnect
            return;
        }

        // ...

        this.Socket.BeginReceive...;
    }
    catch // SocketException
    {
        // abnormal disconnect
    }
}

现在,由于我已经读过它并不容易,我想知道我的方法是否有问题。在那儿?或者杀戮过程和牵引电缆之间有区别吗?

1 个答案:

答案 0 :(得分:12)

完全可能并且可以做到这一点。一般的想法是:

如果EndReceive返回零以外的任何内容,则需要处理传入数据。

如果EndReceive返回零,则远程主机已关闭其连接结束。这意味着它仍然可以接收您发送的数据,如果它被编程为这样做,但在任何情况下都不能发送它自己的数据。通常在发生这种情况时,您也会关闭连接,从而完成有序关机,但这不是强制性的。

如果EndReceive抛出,则连接异常终止(进程终止,网络电缆断开,断电等)。

您必须注意以下几点:

  1. EndReceive永远不会返回小于零(代码中的测试会产生误导)。
  2. 如果它抛出,除了SocketException之外,它还会抛出其他类型的异常。
  3. 如果它返回零,你必须小心停止呼叫BeginReceive;否则你将在BeginReceiveEndReceive之间开始一场无限且毫无意义的乒乓球比赛(它将在你的CPU使用中显示)。您的代码已经执行此操作,因此无需更改任何内容。