2014-07-03 39 views
3

我是新来的nio套接字,我写了一个使用nio套接字的服务器,现在我正在尝试写关闭挂钩来确保通过清理资源的优雅退出。Selector.close()是否关闭所有客户端套接字?

我的问题是Selector.close()方法关闭所有的客户端套接字?如果不是,请让我知道如何访问所有客户端套接字而无需单独列出它们。

的Java医生说下面为selector.close()方法

关闭此选择。

如果一个线程当前被阻塞在这个 选择器的选择方法之一中,那么它就像调用 选择器的唤醒方法一样被中断。

与此选择器相关的任何未被取消的密钥都是无效的,它们的信道被取消注册,并且与此选择器相关联的任何其他资源 被释放。

如果此选择器已关闭,则调用此方法没有 效果。

选择器关闭后,除 调用此方法或唤醒方法外,如果进一步尝试使用该选择器,将导致引发一个 ClosedSelectorException。

上面的描述使用了“取消注册”这个词,它给人一种感觉,它不会关闭套接字,而只是从选择器中移除它们的映射。

回答

6

不,它只关闭选择器。

在关闭选择器之前,可以通过Selector.keys()访问所有已注册的套接字密钥。

+0

我期待这一点,将标记它给它一个答案后回答。谢谢 –

1

感谢EJP指出我正确的方向,但我们必须记住,密钥也包含serverSocketChannel。无论如何,下面的代码在关机时为我工作,以防您正在寻找一段代码。

if(this.serverChannel != null && this.serverChannel.isOpen()) { 

    try { 

     this.serverChannel.close(); 

    } catch (IOException e) { 

     log.error("Exception while closing server socket"); 
    } 
} 

try { 

    Iterator<SelectionKey> keys = this.selector.keys().iterator(); 

    while(keys.hasNext()) { 

     SelectionKey key = keys.next(); 

     SelectableChannel channel = key.channel(); 

     if(channel instanceof SocketChannel) { 

      SocketChannel socketChannel = (SocketChannel) channel; 
      Socket socket = socketChannel.socket(); 
      String remoteHost = socket.getRemoteSocketAddress().toString(); 

      log.info("closing socket {}", remoteHost); 

      try { 

       socketChannel.close(); 

      } catch (IOException e) { 

       log.warn("Exception while closing socket", e); 
      } 

      key.cancel(); 
     } 
    } 

    log.info("closing selector"); 
    selector.close(); 

} catch(Exception ex) { 

    log.error("Exception while closing selector", ex); 
} 
+0

这一切都很好,但为什么中断现有的连接呢?你真正应该做的是关闭ServerSocket,所以没有新的连接,然后继续选择,直到没有更多的注册密钥,当客户端关闭他们的连接或者你自己关闭它们时自动关闭连接。 – EJP

+0

你说得对,但我们的要求有点不同。 –

相关问题