这不是关于如何做到这一点的问题,而是一个关于我做错的问题。我已经读过,在等待数据(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
}
}
现在,由于我已经读过它并不容易,我想知道我的方法是否有问题。在那儿?或者杀戮过程和牵引电缆之间有区别吗?
答案 0 :(得分:12)
完全可能并且可以做到这一点。一般的想法是:
如果EndReceive
返回零以外的任何内容,则需要处理传入数据。
如果EndReceive
返回零,则远程主机已关闭其连接结束。这意味着它仍然可以接收您发送的数据,如果它被编程为这样做,但在任何情况下都不能发送它自己的数据。通常在发生这种情况时,您也会关闭连接,从而完成有序关机,但这不是强制性的。
如果EndReceive
抛出,则连接异常终止(进程终止,网络电缆断开,断电等)。
您必须注意以下几点:
EndReceive
永远不会返回小于零(代码中的测试会产生误导)。SocketException
之外,它还会抛出其他类型的异常。BeginReceive
;否则你将在BeginReceive
和EndReceive
之间开始一场无限且毫无意义的乒乓球比赛(它将在你的CPU使用中显示)。您的代码已经执行此操作,因此无需更改任何内容。