我想首先将一个频道注册到选择器,仅在连接时执行select()
,然后在只写时执行。{/ p>
类似的东西:
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()
等。
答案 0 :(得分:1)
如果finishConnect()
返回false,则表示无法正确处理,就好像它已返回true一样。
你的问题是你没有在取消和注册之间调用选择器,所以有未完成的业务。这里最简单的解决方案是删除取消和寄存器,直接调整现有选择键的interestOps。
然而,由于您只是在连接完成之前才有效阻塞,因此在阻塞模式下进行连接会更简单,之后会进入非阻塞状态,对于后续的I / ○:
// Still in blocking mode, no register() yet ...
server.socket().connect(address, connectTimeout);
server.configureBlocking(false);
key = server.register(selector, SelectionKey.OP_WRITE);
...注意如果超时到期,则抛出异常。
我很少遇到一个案例,其中在客户端实际上在非阻塞模式下使用NIO是有意义的。