Java 注册多重选择键
我正在NIO中使用Java选择器。我正在向特定频道和选择器注册我的选择密钥/兴趣密钥。现在,我的要求是为一个特定选择器设置两个或多个兴趣集 我所做的是制作两个具有不同选择选项的SelectionKey,如下所示:Java 注册多重选择键,java,nio,channel,Java,Nio,Channel,我正在NIO中使用Java选择器。我正在向特定频道和选择器注册我的选择密钥/兴趣密钥。现在,我的要求是为一个特定选择器设置两个或多个兴趣集 我所做的是制作两个具有不同选择选项的SelectionKey,如下所示: try { Selector selector = Selector.open(); ServerSocketChannel channel = ServerSocketChannel.open(); //FileChannel
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();
}
我的问题是,有什么方法可以避免生成两个不同的键吗?您可以将两个键或两个键组合在一起以创建一个单独的兴趣:
SelectionKey key = channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
您可以将二进制或键组合在一起创建单个兴趣:
SelectionKey key = channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
不过,一个老问题需要注意 请注意,在同一频道上调用
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);
这不仅仅是注册两个事件的更好方法--否则它不起作用一个老问题,尽管需要注意 请注意,在同一频道上调用
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);
这不仅仅是注册两个事件的更好方法--否则它不起作用更常见的名称是“按位或”,更常见的名称是“按位或”