2013-05-05 70 views
3

我正在编写一个连接到服务器的Android应用程序(> = 2.3),并且我遇到了NIO选择器的问题。Android:Selector.select()立即返回0

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 documentation

公共抽象INT的select()
此方法不返回,直到至少一个信道准备好时,唤醒()被调用或调用线程被中断。

和的情况下落入这些都不但它返回。 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(); 
} 

当服务器在运行它的工作原理:选择()1个选择键返回,我可以打电话finishConnect()建立连接。但是如果服务器没有运行,连接被拒绝,select()会返回0个选定的键。如果没有选定的密钥,我无法确定接下来要做什么。 (并再次,这种情况并不在API文档中描述的select()返回落入3个类别之一。)

回答

0

试试您注册前的插座连接到一些东西。在将其放入非阻塞模式之前,要么执行此操作,要么在之后执行该操作,而是在注册OP_CONNECT而不是OP_READ并在触发时调用finishConnect():如果它返回true,则注销OP_CONNECT并注册OP_READ。

+0

感谢您的回复。如果服务器关闭并且连接被拒绝,该怎么办?在这种情况下,select()返回0并且selectedKeys()为空,那么如何知道连接失败并处理了这种情况? – 2013-05-06 08:34:18

+0

问题是,当连接失败时,select()会返回没有正确设置selectedKeys()的值。即使连接失败,也应该选择密钥,以便随后调用finishConnect()可以捕获异常以知道它失败。这就是在Java文档中指定的OP_CONNECT的行为,如果Andoroid不遵循它,它就像一个错误。 – 2013-05-06 10:37:42

+0

你错过了这一点。在上面的代码中,您正在调用select * *连接套接字。这是回到前面。在调用connect()之后,isConnectable()发生*,并且这是一个信号,您应该尝试调用finishConnect()。这不是您现在可以调用connect()的信号。你不需要等待任何事情。 – EJP 2013-05-06 23:16:55