我正在尝试使用Java NIO。一切都很好,直到我试图在模拟器无法访问互联网时测试连接。接下来是结果:
在2.2中select()选择1个键,然后在finishConnect()调用之后抛出异常。正如所料。但它仅在第一行未注释时才起作用(preferIPv6 = false)。
但是在4.1.2中,select()总是返回零。选定的键设置为空。检查值表示,该选择键始终没有为任何操作做好准备,interestOps为8(OP_CONNECT)。
在java connect()中调用throw IOException:网络无法访问。正如所料。
我做错了什么以及如何导致select()阻止?
//System.setProperty("java.net.preferIPv6Addresses", "false");
try {
Selector selector = Selector.open();
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
boolean connected = socketChannel.connect(new InetSocketAddress("173.194.44.3", 80));
SelectionKey selectionKey;
if (connected) {
selectionKey = socketChannel.register(selector, SelectionKey.OP_READ);
} else {
selectionKey = socketChannel.register(selector, SelectionKey.OP_CONNECT);
}
while (true) {
int selected = selector.select();
if (selected == 0) continue;
for (SelectionKey key : selector.selectedKeys()) {
if (socketChannel.finishConnect()) {
key.interestOps(SelectionKey.OP_READ);
}
}
selector.selectedKeys().clear();
}
} catch (IOException e) {
throw new RuntimeException("IOException", e);
}
感谢。
答案 0 :(得分:0)
问题看起来可以解决。
我添加了OP_READ兴趣和某些选择器选择键,准备好阅读。
但是当我试图阅读时,NotYetConnectedException抛出了。所以,我可以抓住这个并处理这个问题。然后,选择块。
但它看起来像虫子。
try {
Selector selector = Selector.open();
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
boolean connected = socketChannel.connect(new InetSocketAddress("173.194.44.3", 80));
SelectionKey selectionKey;
int validOps = socketChannel.validOps();
if (connected) {
selectionKey = socketChannel.register(selector, SelectionKey.OP_READ);
} else {
selectionKey = socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ);
}
ByteBuffer buffer = ByteBuffer.allocate(512);
while (true) {
int selected = selector.select();
if (selected == 0) continue;
for (SelectionKey key : selector.selectedKeys()) {
SocketChannel sc = (SocketChannel) key.channel();
if ((key.interestOps() & SelectionKey.OP_CONNECT) != 0 && key.isConnectable())
{
if (socketChannel.finishConnect()) {
key.interestOps(SelectionKey.OP_READ);
}
}
if (key.isReadable()) {
while (true) {
int readed = 0;
try {
readed = sc.read(buffer);
} catch (Exception e) {
sc.close();
}
if (readed == 0) break;
if (readed == -1) throw new RuntimeException("Closed");
}
}
}
selector.selectedKeys().clear();
}
} catch (IOException e) {
throw new RuntimeException("IOException", e);
}
也许这里存在更多“非魔法”解决方案?
答案 1 :(得分:0)
如果select()
返回零,则某些内容已超时。您不应该只是继续,您应该将其视为错误或警告。例如,如果您选择等待OP_CONNECT
触发60秒并且select()
返回零,则应将其视为连接超时。