2013-05-05 74 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