检查 OP_ACCEPT-ed 选择键是否有等待打开的连接

Check if OP_ACCEPT-ed Selection key has waiting connection to open

考虑到我使用选择器来处理用户连接:

初始化:

this.channel = ServerSocketChannel.open();

this.channel.socket().bind(new InetSocketAddress(4321));
this.channel.configureBlocking(false);

this.selector = Selector.open();
this.channel.register(selector, SelectionKey.OP_ACCEPT);

主循环:

while (this.channel.isOpen()) {
    selector.select();
    for (SelectionKey key : this.selector.selectedKeys()) {
        if (key.isAcceptable()) this.acceptNewConnection(key);
        else if (key.isReadable()) this.readFromConnection(key); 
    }
}

正在接受连接:

private void acceptNewConnection(SelectionKey key) throws IOException {
    final SocketChannel channel = SelectionKeyHelpers.getServerSocketChannel(key).accept();
    final String address = SocketHelpers.getConnectorAddres(channel.socket());

    channel.configureBlocking(false);
    channel.register(this.selector, SelectionKey.OP_READ, address);
}

一切正常...接受第一个连接并添加新的选择键(OP_READ)。

问题是当一些数据准备好读取时,selectedKeys() returns 集合有两个选择键:一个要读取,另一个用 OP_OPEN 尽管没有连接访问(在本例中 isAcceptable returns 也是如此)。因此,从该 SelectionKey 获取套接字(在 acceptNewConncetion 中)returns null.

所以..当没有可用的新连接时,有什么方法可以从 selectedKeys() 中排除带有 OP_OPEN 的选择键吗?

检查 socket channel == null 是否足够或有更合适的方法? f.e:

final SocketChannel channel = SelectionKeyHelpers.getServerSocketChannel(key).accept();
if (channel == null) {
    // key is selected but there is nothing to accept
    return;
}
  1. 没有OP_OPEN。
  2. 这里的问题是您的代码中的错误。您需要从所选密钥集中删除每个已处理的密钥。选择器从不这样做。