3

我正在编写一个连接到服务器的 Android 应用程序 (>= 2.3),但 NIO 选择器有问题。

Selector selector = SelectorProvider.provider().openSelector();
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);

selector.select();  // returns 0 immediately

根据Android API 文档

public abstract int select()
在至少一个通道准备好、调用wakeup() 或调用线程被中断之前,该方法不会返回。

案件不属于这些,但它会返回。select() 的行为不符合规范中的描述,我认为这是一个错误。

编辑

我根据以下 EJP 的评论更改了代码:

socketChannel.register(selector, SelectionKey.OP_CONNECT);
socketChannel.connect(serverAddress);

while (true) {
  selector.select();

  for (SelectionKey key: _selector.selectedKeys()) {
    if (key.isConnectable())
      finishConnect(key);
    ...
  }
  selector.selectedKeys().clear();
}

它在服务器运行时工作:select() 返回 1 个选定的键,我可以调用 finishConnect() 来建立连接。但是如果服务器没有运行因此连接被拒绝, select() 返回 0 个选定的键。如果没有选定的键,我无法确定下一步该做什么。(同样,当 API 文档中描述的 select() 返回时,这种情况不属于 3 个类别之一。)

4

1 回答 1

0

在注册之前尝试将套接字连接到某个东西。要么在将其置于非阻塞模式之前执行此操作,要么在之后执行此操作但注册 OP_CONNECT 而不是 OP_READ 并在它触发时调用 finishConnect():如果它返回 true,则取消注册 OP_CONNECT 并注册 OP_READ。

于 2013-05-05T21:20:02.377 回答