先决条件: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一起使用?
以下代码适用于Java
此代码在任何平台上都存在重大问题.
你没有清理selectedKeySet.通常这是通过迭代它并调用来完成的Iterator.remove(),但在这种情况下你应该调用,selectedKeys().clear()因为你没有这样做,尽管你应该这样做:见下文.
您不应该注册interestOps = validOps().您应该注册,OP_CONNECT直到finishConnect()返回true,然后注册OP_READ或者OP_WRITE,取决于您下一步要做什么.
如果连接不成功,则finishConnect()抛出一个IOException应关闭通道的连接.你不是那样做的.
如果连接尚未完成,则finishConnect()返回false,在这种情况下,您应该继续选择.在那一点取消密钥没有任何意义.
如果selres > 1您根本没有处理任何选定的键.测试应该是if (selRes > 0),并且实际上并不是必需的,因为迭代selectedKeySet将只迭代零次; 但是selRes == 0确实表示select()超时,如果您想考虑超时,这可能很有用.
| 归档时间: |
|
| 查看次数: |
2911 次 |
| 最近记录: |