5

这不是关于如何做到这一点的问题,而是关于我正在做的事情是否错误的问题。我读过,在等待数据(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
    }
}

现在,由于我已经阅读了这并不容易,我想知道我的方法是否有问题。有没有?还是杀死过程和拉电缆等有区别?

4

1 回答 1

12

这样做是完全有可能的并且可以的。总体思路是:

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

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

如果EndReceivethrows,则连接异常终止(进程终止、网线断开、断电等)。

您需要注意的几点:

  1. EndReceive永远不能返回小于零(代码中的测试具有误导性)。
  2. 如果它抛出它可以抛出除了SocketException.
  3. 如果它返回零,你必须小心停止调用BeginReceiveBeginReceive否则,您将在和之间开始一场无限且毫无意义的乒乓球比赛EndReceive(它将显示在您的 CPU 使用率中)。您的代码已经这样做了,因此无需更改任何内容。
于 2012-07-05T08:21:40.933 回答