Selector.close()是否关闭所有客户端套接字?

时间:2014-07-03 01:39:03

标签: java sockets network-programming nio

我是nio套接字的新手,我已经使用nio套接字写了一个服务器,现在我正在尝试编写shutdown hook以确保通过清理资源来优雅退出。

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

Java Doc说跟随selector.close()方法

  

关闭此选择器。

     

如果其中一个线程当前被阻止   选择器的选择方法然后它就像通过调用一样被中断   选择器的唤醒方法。

     

仍然与此选择器关联的任何未取消的键都是   无效,其渠道已取消注册,以及任何其他资源   与此选择器关联的已释放。

     

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

     

选择器关闭后,进一步尝试使用它,除了   调用此方法或唤醒方法,将导致   ClosedSelectorException将被抛出。

以上描述使用word" deregistered"这给人一种感觉,它不会关闭套接字,只是从选择器中删除它们的映射。

2 个答案:

答案 0 :(得分:6)

不,它只会关闭选择器。

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

答案 1 :(得分: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);
}