我有使用非阻塞IO的工作代码来获取这样的UDP数据包:
DatagramChannel channel = DatagramChannel.open();
channel.socket().bind(new InetSocketAddress(AUDIO_PORT));
channel.configureBlocking(false);
while(true){
ByteBuffer packet = ByteBuffer.allocate(MAX_PACKET);
if(channel.receive(packet) != null){
//Got something!
...
}
...
}
完美无缺。 现在我正在尝试完全相同,只是这次我想使用选择器,如下:
//Create a datagram channel, bind it to port, configure non-blocking:
DatagramChannel channel = DatagramChannel.open();
channel.socket().bind(new InetSocketAddress(AUDIO_PORT));
channel.configureBlocking(false);
//Create a selector and register it:
Selector selector = Selector.open();
channel.register(selector, SelectionKey.OP_READ);
//Spin
while(true){
//If there's a packet available, fetch it:
if(selector.selectNow() >= 1){
//**CODE NEVER REACHES THIS POINT**
ByteBuffer packet = ByteBuffer.allocate(MAX_PACKET);
channel.receive(packet);
...
}
...
}
由于我正在制作的应用程序,我真的需要它是非阻塞IO(即使看起来我只是在我的示例中旋转),并且使用短暂超时阻塞将无法正常工作。我也必须使用选择器。问题是,即使我有一台服务器主动将数据包发送到设备的AUDIO_PORT端口,select()操作也始终返回0.我知道服务器应用程序正在执行其工作,因为第一个代码段工作正常。我设置选择器错了吗?我猜我错过了一些步骤,但我无法弄明白。
答案 0 :(得分:1)
我相信我们之前在其他主题中已经讨论过,如果第一个代码有效,第二个代码没有,那么选择器必须在Android中被破解。您的代码是正确的(只要您每次获得非零返回时清除选择器的选定键集)。您可以通过在Java平台上运行它来验证它。
您可以考虑将select() == 1
更改为select() > 0
以获得更大的通用性,然后循环选择键集,如您将在所有示例中看到的那样,但它不应影响此正确性代码。
正如我也相信我们已经讨论过,您可以尝试使用短读取超时而不是选择器来阻止模式。
注意:你没有在旋转,你在select().