你如何干净地关闭 AsynchronousSocketChannel?

Posted

技术标签:

【中文标题】你如何干净地关闭 AsynchronousSocketChannel?【英文标题】:How do you close a AsynchronousSocketChannel cleanly? 【发布时间】:2014-01-11 19:44:32 【问题描述】:

我的服务器使用AsynchronousServerSocketChannel,它使用CompletionHandler 侦听客户端连接。当客户端连接被接受时,AsynchronousSocketChannel 被读取,再次使用CompletionHandler 接收数据,没有超时。

到目前为止一切顺利,我的客户端连接,写入服务器读取的数据,服务器能够响应通过同一个套接字将数据发送回客户端。

当我的客户端终止时,它会调用AsynchronousSocketChannel.close() 来关闭套接字。进行此调用时,服务器正在等待从套接字读取数据。

我曾预计客户端上对AsynchronousSocketChannel.close() 的调用会转换为对服务器上-1 的读取长度的CompletionHandler.completed 的回调,表明套接字已关闭,但回调是对@987654329 @ 除了以下例外:

java.io.IOException: The specified network name is no longer available.
  at sun.nio.ch.Iocp.translateErrorToIOException(Iocp.java:309)
  at sun.nio.ch.Iocp.access$700(Iocp.java:46)
  at sun.nio.ch.Iocp$EventHandlerTask.run(Iocp.java:399)
  at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  at java.lang.Thread.run(Thread.java:744)    

客户端应该如何关闭一个套接字,以便它在服务器上不被视为错误?

【问题讨论】:

【参考方案1】:

documentation on close 表示它会导致 另一端的 AsynchronousCloseException 或 ClosedChannelException。

要引起completed(-1),客户端应该调用shutdownInput。

但是,我会将 AsynchronousCloseException 和 ClosedChannelException 视为正常关闭,以及 completed(-1)。

【讨论】:

它没有提到“另一边”。这两个异常都应该被视为编程错误,而不是“正常关机”。 我在客户端添加了对AsynchronousSocketChannel.shutdownInput的调用,这确实会导致在服务器上以-1的读取长度回调CompletionHandler.completed 很遗憾客户端得到了一个AsynchronousCloseException,尽管至少它不是很一般的IOException,并且因为客户端启动了关闭,我可以添加一个closing标志以便忽略此错误。 @EJP - 你知道完全避免AsynchronousCloseException 的方法吗? 我也被这种行为难住了...如果客户端使用有效方法关闭连接,为什么会抛出异常?我想知道。这就像您每次关闭车门时都会触发汽车警报一样......

以上是关于你如何干净地关闭 AsynchronousSocketChannel?的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat 上的 Websockets:如何干净地关闭服务器?

如何使用 Ctrl+C 输入干净地退出 QProcess?

在多线程 HTTP 服务器中发送后,如何干净地关闭套接字?

线程 python 应用程序没有干净地关闭

boost::asio 无法干净地关闭 TCP 连接

关闭 Android 应用程序 [重复]