取消选择键但之后重新使用它
Cancel a selection key but reuse it afterwards
我想首先将通道注册到选择器以仅在连接时执行 select()
,然后在仅写入时执行。
像这样:
SelectionKey key = server.register(selector, SelectionKey.OP_CONNECT);
server.connect(address);
int readyChannels = 0;
while (readyChannels == 0) readyChannels = selector.select(config.connectTimeout);
server.finishConnect();
key.cancel();
key = server.register(selector, SelectionKey.OP_WRITE);
// write something to the channel and check timeout
// with selector.select(config.writeTimeout)
但是,当我到达代码中的第二个 register(...)
时,我得到一个 CancelledKeyException
。
还有其他方法吗?
正确的做法是每次都定义一个新的选择器吗?
P.S。我知道我可以使用 key.isWritable()
等等。
如果 finishConnect()
returns false 就好像返回了 true 一样继续进行是不正确的。
你的问题是你没有在取消和注册之间调用选择器,所以还有未完成的事情。这里最简单的解决办法就是去掉cancel和register,直接调整已有selection key的interestOps即可。
然而,由于您只是在连接完成之前有效地阻塞,所以在 in 阻塞模式下执行连接并转到非阻塞会更简单之后,对于随后的 I/O:
// Still in blocking mode, no register() yet ...
server.socket().connect(address, connectTimeout);
server.configureBlocking(false);
key = server.register(selector, SelectionKey.OP_WRITE);
...注意,如果超时到期,将引发异常。
实际上,我很少遇到在客户端中以非阻塞模式使用 NIO 有意义的情况。
我想首先将通道注册到选择器以仅在连接时执行 select()
,然后在仅写入时执行。
像这样:
SelectionKey key = server.register(selector, SelectionKey.OP_CONNECT);
server.connect(address);
int readyChannels = 0;
while (readyChannels == 0) readyChannels = selector.select(config.connectTimeout);
server.finishConnect();
key.cancel();
key = server.register(selector, SelectionKey.OP_WRITE);
// write something to the channel and check timeout
// with selector.select(config.writeTimeout)
但是,当我到达代码中的第二个 register(...)
时,我得到一个 CancelledKeyException
。
还有其他方法吗?
正确的做法是每次都定义一个新的选择器吗?
P.S。我知道我可以使用 key.isWritable()
等等。
如果
finishConnect()
returns false 就好像返回了 true 一样继续进行是不正确的。你的问题是你没有在取消和注册之间调用选择器,所以还有未完成的事情。这里最简单的解决办法就是去掉cancel和register,直接调整已有selection key的interestOps即可。
然而,由于您只是在连接完成之前有效地阻塞,所以在 in 阻塞模式下执行连接并转到非阻塞会更简单之后,对于随后的 I/O:
// Still in blocking mode, no register() yet ... server.socket().connect(address, connectTimeout); server.configureBlocking(false); key = server.register(selector, SelectionKey.OP_WRITE);
...注意,如果超时到期,将引发异常。
实际上,我很少遇到在客户端中以非阻塞模式使用 NIO 有意义的情况。