我是nio套接字的新手,我已经使用nio套接字写了一个服务器,现在我正在尝试编写shutdown hook以确保通过清理资源来优雅退出。
我的问题是Selector.close()
方法是否会关闭所有客户端套接字?如果没有,请告诉我如何访问所有客户端套接字,而无需单独列出它们。
Java Doc说跟随selector.close()
方法
关闭此选择器。
如果其中一个线程当前被阻止 选择器的选择方法然后它就像通过调用一样被中断 选择器的唤醒方法。
仍然与此选择器关联的任何未取消的键都是 无效,其渠道已取消注册,以及任何其他资源 与此选择器关联的已释放。
如果此选择器已经关闭,则调用此方法没有 影响。
选择器关闭后,进一步尝试使用它,除了 调用此方法或唤醒方法,将导致 ClosedSelectorException将被抛出。
以上描述使用word" deregistered"这给人一种感觉,它不会关闭套接字,只是从选择器中删除它们的映射。
答案 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);
}