gpt4 book ai didi

java - 非阻塞模式下的 ServerSocketChannel 未正确关闭

转载 作者:行者123 更新时间:2023-12-01 09:28:25 31 4
gpt4 key购买 nike

当 ServerSocketChannel 在非阻塞模式下使用并在选择器中注册时,以下 Channel.close() 调用不会立即关闭套接字,并且它在 LISTENING 状态下的 netstat 输出中仍然可见。

一个简单的测试用例。

// windows 7 / jdk1.8.0_71 x64

@Test
public void test() throws Exception {
Selector selector = Selector.open();

for (int i = 0; i < 3; i++) {
System.out.printf("Trial %d\n", i);
reopen(selector);
}
}

private void reopen(Selector selector) throws Exception {
ServerSocketChannel channel = ServerSocketChannel.open();
channel.configureBlocking(false);
channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
channel.bind(new InetSocketAddress("127.0.0.1", 17777));

// --- if channel is not registered with selector the following close() method works fine
SelectionKey selectionKey = channel.register(selector, SelectionKey.OP_ACCEPT);

// --- trying to cancel the registration in selector - doesn't help
// selectionKey.cancel();
// selector.wakeup();

// --- trying to configure the socket as blocking - doesn't help
// selectionKey.cancel();
// channel.configureBlocking(true);

// --- trying to register the channel in other selector - doesn't help
// selectionKey.cancel();
// Selector nullSelector = Selector.open();
// channel.register(nullSelector, 0);
// nullSelector.close();

channel.close();

// PROBLEM: after close() has returned I still see this port is listening
//
// C:\Dev>netstat -nao | grep 17777
// TCP 127.0.0.1:17777 0.0.0.0:0 LISTENING xxxx
//
// so on the next bind I get an exception: java.net.BindException: Address already in use: bind

// --- it helps!!! but I don't want to because there could multiple server sockets on the same selector
// selector.close();

// --- trying to shake-up the selector - doesn't help
// selector.wakeup();

// --- trying to wait some time - doesn't help
// Thread.sleep(10000);
}

正确关闭 ServerSocketChannel 的唯一机会是关闭选择器本身。但选择器用于其他套接字,我不想关闭它。

如何在不关闭选择器的情况下正确关闭ServerSocketChannel?或者如何等到它关闭?

UPD:问题仅发生在 Windows 上。解决方案已找到并发布在下面的评论中。

最佳答案

在尝试了很多选项之后,我发现这段代码有帮助:

channel.close();

selector.selectNow();

selectionKey.cancel();
selector.selectNow();

channel.close();

但我不知道为什么它会起作用。也许有人会解释这一点。

关于java - 非阻塞模式下的 ServerSocketChannel 未正确关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39656477/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com