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

C#:如何在socket.BeginReceive回调之前终止套接字?,c#,tcp,sockets,connection,C#,Tcp,Sockets,Connection,我有一个从客户端接收连接请求的服务器。此服务器使用异步Socket.BeginReceive和Socket.EndReceive方法。代码与找到的代码非常相似 在我的例子中,在调用Socket.BeginReceive后,我需要一个超时,这样,如果客户端挂起连接,但在固定的时间内根本不传输任何数据,我就需要终止连接 我该如何着手终止合同 这种情况下的连接 什么是编写代码的最佳方法 计时器 根据MSDN关于它的文章所述 要取消挂起的BeginReceive,请调用Close方法 您可以异步接收一

我有一个从客户端接收连接请求的服务器。此服务器使用异步
Socket.BeginReceive
Socket.EndReceive
方法。代码与找到的代码非常相似

在我的例子中,在调用Socket.BeginReceive后,我需要一个超时,这样,如果客户端挂起连接,但在固定的时间内根本不传输任何数据,我就需要终止连接

  • 我该如何着手终止合同 这种情况下的连接
  • 什么是编写代码的最佳方法 计时器

根据MSDN关于它的文章所述

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


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

但如果您只想使用异步接收,那么可以使用计时器并在EndReceive上重置它们。如果它过去了,您可以强制断开客户端


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

只需调用套接字的
Close()
方法即可。回调方法将很快运行,在调用
EndReceive()
方法时,您将得到一个
ObjectDisposedException
。准备好抓住这个例外


您可能不想阻止调用
BeginReceive
的线程,您需要一个
System.Threading.Timer
System.Timers.Timer
来检测超时。它的回调应该调用
Close()
。注意这会导致不可避免的竞争情况,如果在计时器过期前一微秒收到响应,则计时器的回调将运行。您将关闭插座,即使您得到了良好的响应。对
BeginReceive()
的下一次调用将立即失败。

我知道这个线程很旧,但我刚刚遇到了同样的问题,我对这里给出的答案(或其他任何地方的答案)不满意

取消挂起的
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();
}

因此,您甚至不需要调整异步回调来处理手动取消。

您的意思是调用套接字的close方法后回调方法仍将运行吗?如果BeginReceive()挂起:是。它必须始终与EndReceive()调用配对。你无法避免回调。我整天都在寻找这个问题的解决方案。感谢您的深入回复。我从未预料到会出现异常,但我对.NET编程还是相当陌生。请引用Close方法的文档:“对于面向连接的协议,建议在调用Close方法之前调用Shutdown。这样可以确保在关闭连接的套接字之前,所有数据都在该套接字上发送和接收。”