注册多个SelectionKey

问题描述 投票:0回答:2

我正在使用NIO中的Java选择器。我正在使用特定频道和选择器注册我的选择键/兴趣键。现在,我的要求是为特定选择器设置两个或更多兴趣集。

我所做的是制作两个具有不同选择选项的选择键,如下所示:

    try {
        Selector selector = Selector.open();
        ServerSocketChannel channel = ServerSocketChannel.open();
        //FileChannel channel = new FileInputStream("").getChannel();

        channel.configureBlocking(false);

        SelectionKey key1 = channel.register(selector, SelectionKey.OP_READ);
        SelectionKey key2 = channel.register(selector, SelectionKey.OP_WRITE);

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

我的问题是,无论如何我可以避免制作两个不同的键吗?

java nio channel
2个回答
0
投票

您可以将二进制或键一起创建单个兴趣:

SelectionKey key = channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

0
投票

一个老问题,虽然需要注意。

请注意,在同一通道上调用register两次不会添加额外的注册,但会替换之前的注册。

OP提供的代码有几个值得关注的问题:

try {
    Selector selector = Selector.open();
    ServerSocketChannel channel = ServerSocketChannel.open();

    channel.configureBlocking(false);

    //====================================================================
    // NOTE:
    // this is not good - see notes below...
    //====================================================================

    SelectionKey key1 = channel.register(selector, SelectionKey.OP_READ);
    SelectionKey key2 = channel.register(selector, SelectionKey.OP_WRITE);

    //====================================================================

    // NOTE 1:
    // the 2nd call to channel.register causes the channel to be registered
    // only for OP_WRITE, replacing the registration for OP_READ.
    // So both lines together makes the first one redundant 'dead code'.

    // NOTE 2:
    // the key returned in both calls would be the same as the key is
    // associated with the channel, regardless of the events we register for 
    // (changing the registration doesn't change the SelectionKey, it only
    // sets another registration for this key).

    // NOTE 3:
    // ServerSocketChannel should not be registered for OP_READ, OP_WRITE...
    // ServerSocketChannel should be registered for OP_ACCEPT
    // You may register SocketChannel to OP_READ and OP_WRITE

    //====================================================================

} catch (IOException e) { // ...

因此,正如已经指出的那样,正确的方法是使用按位 - 或者,使用以下附加修复:

    SocketChannel clientChannel = serverSockChannel.accept();
    clientChannel.configureBlocking(false);
    SelectionKey key =
      clientChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

这不仅仅是注册两个事件的更好方式 - 否则不起作用。

© www.soinside.com 2019 - 2024. All rights reserved.