如何从服务器优雅地关闭套接字

5
在服务器端,我正在尝试优雅地关闭连接的套接字。我知道套接字上的正确事件序列应该是:
1. 使用SocketShutdown.Send选项关闭套接字 2. 循环/等待直到socket Receive返回0个字节 3. 关闭套接字
我有一些问题:
1. 如果Socket.Receive永远不返回(零字节)怎么办?我们会一直尝试关闭套接字吗? 2. 每当我在服务器上调用Close时,客户端总是收到“现有连接被远程主机强制关闭”的异常。如何更“优雅”地通知客户端关闭连接? 3. 在服务器上,如果我使用异步Begin/EndReceive调用,每当我调用套接字上的Close时,它总是在Begin/EndReceive线程上导致ObjectDisposedException异常。是否有没有这种异常发生的关闭套接字方式?
1个回答

2
  1. TCP协议保证套接字最终会关闭,除非对等方拒绝关闭。在这种情况下,您应该永远等待或放弃,具体取决于情况。

  2. 如果在receive返回零后关闭套接字,那是不应该发生的。如果出现了这种情况,您的代码可能存在问题。

  3. 在异步操作正在使用资源或可能正在使用资源时,不能释放该资源。与其调用close,不如调用shutdown。在100%完成资源之前,请勿调用close。


感谢您的回复!与#1和#2相关:什么导致服务器端接收到的字节数为0?也就是说,在服务器调用Shutdown之后,客户端会看到什么,并且客户端需要做什么来确保服务器获得适当的断开连接事件(即接收字节== 0)?对于#3:即使您知道100%完成了资源,也没有办法从异步操作中“中断”套接字。 MSDN指示调用Close退出异步循环,但在我的经验中,这总是导致ObjectDisposedException发生。 - shyneman
客户端做同样的事情,关闭套接字并接收数据直到收到零。一旦TCP连接建立起来,实际上没有真正的区别。打破异步操作的方法是关闭底层连接。此时异步操作应该完成。 - David Schwartz
客户端何时知道调用Shutdown(如果是服务器启动了Shutdown)? - shyneman
我一直在进行自己的测试,但似乎无论如何都无法使服务器端在由服务器发起关闭时接收到零字节。如果服务器发起关闭,则客户端将接收到零字节,但如果客户端不调用关闭,则服务器永远不会收到0字节的返回。你是说服务器应该期望客户端在接收到零字节后调用关闭吗? - shyneman
当服务器调用关闭时,客户端最终会收到0字节。此时,客户端可以调用关闭然后关闭(或者只是关闭,这将自动调用关闭),这将导致服务器接收到0字节。然后,服务器可以调用Close而不生成任何异常(即使在异步调用中,就像您所说的那样)。你说的一切都是正确的...我只是需要思考来理解整个情况。谢谢! - shyneman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接