检测意外的插座断开连接

Mar*_*ars 5 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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*Jon 12

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

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

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

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

有几点你必须注意:

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

  • +1我还想指出,除非重新抛出它,否则你永远不应该有一个抓住所有内容的catch语句. (2认同)