首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >非阻塞模式下的ServerSocketChannel未正确关闭

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

Stack Overflow用户
提问于 2016-09-23 16:44:45
回答 1查看 703关注 0票数 1

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

一个简单的测试用例。

代码语言:javascript
运行
复制
// 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?或者如何等待它被关闭?

更新:仅在Windows上出现问题。在下面的评论中找到并发布了解决方案。

EN

Stack Overflow用户

发布于 2016-09-23 17:13:29

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

代码语言:javascript
运行
复制
channel.close();

selector.selectNow();

代码语言:javascript
运行
复制
selectionKey.cancel();
selector.selectNow();

channel.close();

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

票数 1
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39656477

复制
相关文章

相似问题

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