首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何干净地关闭AsynchronousSocketChannel?

如何干净地关闭AsynchronousSocketChannel?
EN

Stack Overflow用户
提问于 2013-12-23 15:04:52
回答 2查看 2.4K关注 0票数 11

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

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

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

我原以为客户机上对AsynchronousSocketChannel.close()的调用将转换为对CompletionHandler.completed的回调,服务器上的读取长度为-1,指示套接字已关闭,但是回调是对CompletionHandler.failed的,但有以下例外:

代码语言:javascript
复制
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)    

客户端应该如何关闭套接字,使其不被视为服务器上的错误?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-23 19:05:26

关于关闭的文件说它会导致AsynchronousCloseException或ClosedChannelException在另一边。

要导致completed(-1),客户端应该调用shutdownInput

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

票数 3
EN

Stack Overflow用户

发布于 2022-04-20 20:45:17

查看堆栈跟踪和实现源,您可能会注意到,异常是由内部sun.nio.ch.UnixAsynchronousSocketChannelImpl#finish()方法引发的,该方法检查挂起的读/写操作。因此,避免此异常的唯一方法是在某个时候防止新的异步read()write()调用,这应该是应用程序逻辑的一部分。

我已经处理了很多这个异常,在大多数情况下,根本问题在于完成处理程序无条件地“继续侦听”调用:

代码语言:javascript
复制
conn.read(src, attachment, new CompletionHandler<Integer, T>() {
    @Override
    public void completed(Integer result, T attachment) {
        // Some business logic here
        
        // Below is the problem - unconditional read() call
        conn.read(src, attachment, this);
    }

    @Override
    public void failed(Throwable t, T attachment) {
        // Exception handling
    }
});

要优雅地关闭连接,不应该有无条件的异步读/写调用。要实现这一点,可能需要发送额外的消息,这意味着不需要新的异步数据,并且关闭连接是安全的。正确的伪代码应该如下所示:

代码语言:javascript
复制
conn.read(src, attachment, new CompletionHandler<Integer, T>() {
    @Override
    public void completed(Integer result, T attachment) {
        // Some business logic here

        if(continueListening()) {
            conn.read(src, attachment, this);
        }
    }
    
    // ... 

});
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20746091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档