C#:如何在Socket.BeginReceive回调之前终止套接字?

时间:2009-12-17 12:58:19

标签: c# tcp sockets connection

我有一台服务器接收来自客户端的连接请求。此服务器使用异步Socket.BeginReceiveSocket.EndReceive方法。该代码与找到的代码here非常相似。

在我的情况下,在调用Socket.BeginReceive之后我需要一个超时,这样如果客户端挂起连接但是在一段固定的时间内根本不传输任何数据,我需要终止连接。

  • 我该如何终止 这种情况下的连接?
  • 编码的最佳方式是什么? 计时器?

4 个答案:

答案 0 :(得分:10)

只需调用套接字的Close()方法即可。之后回调方法会很快运行,当您调用ObjectDisposedException方法时,您将获得EndReceive()。准备抓住那个例外。

您可能不希望阻止调用BeginReceive的线程,您需要System.Threading.TimerSystem.Timers.Timer来检测超时。它的回调应该调用Close()。请注意这导致的不可避免的竞争条件,如果在计时器到期之前收到响应一微秒,则计时器的回调将会运行。即使你得到了很好的回复,你也会关闭套接字。对BeginReceive()的下一次调用将立即失败。

答案 1 :(得分:7)

我知道这个帖子已经很老了,但我遇到了同样的问题,我对这里给出的答案(或其他任何地方的问题)不满意。

取消待审Socket.BeginReceive的更好解决方案是拨打Socket.Shutdown而不是Socket.Close。这样,异步处理程序“正常”引发,对Socket.EndReceive的调用返回0 - >而不是抛出一个丑陋的预期异常。 你应该总是有一个

if (Socket.EndReceive() > 0) {
  //Do something
} else {
  //Socket has been shut down (either by you or the other end of the connection)
  //Now it's "safe" to call Socket.Close
  Socket.Close();
}

所以你甚至不需要调整你的异步回调来处理手动取消。

答案 2 :(得分:0)

根据MSDN关于Socket.BeginReceive的文章,它说明了

  

要取消挂起的BeginReceive,请调用Close方法。

答案 3 :(得分:0)

您可以异步接收一些初始数据,然后对其余数据进行同步接收,并依赖ReceiveTimeout断开客户端连接。您可以使用Socket.Close强制断开客户端。

但是如果你只想使用async Receive,那么你可以使用计时器并在EndReceive上重置它们。如果它过去了,你可以强行断开客户端。

但我认为第一种方法更好。