Android套接字上的选择器表现奇怪

Eug*_*its 3 java android nio

先决条件:Android 2.2模拟器.

我有一个完美的Java代码,它也可以完美地为Android编译.但是有一个奇怪的部分.特别是,似乎java.nio.Selector根本不起作用.

连接期间出现第一个问题.以下代码适用于Java,但不适用于Android(有关详细信息,请参见下文).

socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress(remoteAddr, getRemotePort()));

Selector selector = Selector.open();
socketChannel.register(selector, socketChannel.validOps());

// Wait for an event
int selRes = selector.select(timeout); 
if (selRes == 1)
{
    SelectionKey selKey = (SelectionKey)selector.selectedKeys().iterator().next();
    if (selKey.isValid() && selKey.isConnectable()) {
        // Get channel with connection request
        boolean success = socketChannel.finishConnect();
        if (!success) {
            selKey.cancel();
        }
    }
}                   
Run Code Online (Sandbox Code Playgroud)

我传递超时30000(毫秒,这是30秒),但是选择立即返回selres等于0(在桌面Java上它是1).将套接字切换到阻塞模式工作正常(因此地址,端口和其他东西都可以).

好的,我保持连接阻塞(暂时).但现在我的Accept停止工作 - Selector不会报告传入的连接.再次,使用阻塞套接字摆脱Selector工作.

所以问题是 - Selector在Android中是否可以工作,或者应该重写代码以避免Selector和java.nio一起使用?

use*_*421 6

以下代码适用于Java

此代码在任何平台上都存在重大问题.

  1. 你没有清理selectedKeySet.通常这是通过迭代它并调用来完成的Iterator.remove(),但在这种情况下你应该调用,selectedKeys().clear()因为你没有这样做,尽管你应该这样做:见下文.

  2. 您不应该注册interestOps = validOps().您应该注册,OP_CONNECT直到finishConnect()返回true,然后注册OP_READ或者OP_WRITE,取决于您下一步要做什么.

  3. 如果连接不成功,则finishConnect()抛出一个IOException应关闭通道的连接.你不是那样做的.

  4. 如果连接尚未完成,则finishConnect()返回false,在这种情况下,您应该继续选择.在那一点取消密钥没有任何意义.

  5. 如果selres > 1您根本没有处理任何选定的键.测试应该是if (selRes > 0),并且实际上并不是必需的,因为迭代selectedKeySet将只迭代零次; 但是selRes == 0确实表示select()超时,如果您想考虑超时,这可能很有用.