Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android套接字上的选择器行为异常_Java_Android_Nio - Fatal编程技术网

Java Android套接字上的选择器行为异常

Java Android套接字上的选择器行为异常,java,android,nio,Java,Android,Nio,先决条件:Android 2.2 emulator 我有一个非常好用的Java代码,它也是为Android编译的。但奇怪的部分来了。特别是,java.nio.Selector似乎根本不起作用 第一个问题出现在连接过程中。以下代码适用于Java,但不适用于Android(详细信息请参见下文) 我通过了30000次超时(毫秒,即30秒),但select立即返回,selres等于0(在桌面Java上为1)。将套接字切换到阻塞模式工作正常(所以地址、端口和其他内容都可以) 好的,我让连接阻塞(现在)。但

先决条件:Android 2.2 emulator

我有一个非常好用的Java代码,它也是为Android编译的。但奇怪的部分来了。特别是,java.nio.Selector似乎根本不起作用

第一个问题出现在连接过程中。以下代码适用于Java,但不适用于Android(详细信息请参见下文)

我通过了30000次超时(毫秒,即30秒),但select立即返回,selres等于0(在桌面Java上为1)。将套接字切换到阻塞模式工作正常(所以地址、端口和其他内容都可以)

好的,我让连接阻塞(现在)。但是现在我的Accept停止了工作-选择器不报告传入的连接。同样,通过使用阻塞套接字来摆脱选择器也是有效的

所以问题是——选择器在Android中能工作吗,还是应该重写代码以避免选择器和java.nio一起工作

以下代码适用于Java

此代码在任何平台上都存在重大问题

  • 您没有清除
    selectedKeySet
    。通常,这是通过对其进行迭代并调用
    Iterator.remove()
    来完成的,但是在这种情况下,您应该调用
    selectedKeys().clear()
    ,因为您没有这样做,尽管您确实应该这样做:请参见下文

  • 您不应该使用interestTops=validOps()注册。您应该注册
    OP\u CONNECT
    ,直到
    finishConnect()
    返回true,然后根据下一步的操作,注册
    OP\u READ
    OP\u WRITE

  • 如果连接未成功,
    finishConnect()
    抛出一个
    IOException
    ,您应该在该异常上关闭频道。你没有那样做

  • 如果连接尚未完成,
    finishConnect()
    返回false,在这种情况下,您应该继续选择。在那一点上取消钥匙没有任何意义

  • 如果
    selres>1
    您根本不处理任何选定的关键点。测试应该是
    if(selRes>0)
    ,实际上并不需要,因为在
    selectedKeySet
    上迭代只会迭代零次;但是,<代码> SELRIE==0 确实指示<代码>选择()/代码>超时,如果您想考虑超时,这可能是有用的。


  • 这个问题在Android bug tracker中看似无关的bug报告中找到了一个奇怪的解决方案。Android Emulator不支持IPv6,虽然我没有假装请求IPv6,但默认情况下选择器似乎会尝试在IPv6堆栈上工作

    添加以下行后,我的代码开始正常工作:

    java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
    java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
    

    非常感谢您的评论。由于代码不是我写的,而且选择器是以某种反常的方式设计的,所以理解代码并不容易。但是,您的所有注释都适用于永远不会执行的代码,因为selRes==0。即使我将timeout替换为0(这意味着“无限等待”),代码也会立即返回-没有帮助。此外,此代码在桌面上已经运行多年。我在自己的回答中发布了解决方案。@EugeneMayevski'EldoSCorp其实谁编写的代码并不重要。在这种情况下,代码是“以某种反常的方式设计的”,需要进行修复,以符合API规范:无论它是否这个具体问题完全是另一个问题。EJP你的评论与需要首先解决的真正问题无关。我会给你买一瓶啤酒。我会给你买一包啤酒!我已经调试了一整天我的android应用程序。它在所有网络上都能用,但在我母亲的ISP上不能用。我什么都试过了!很瘦king为此花了一整天的时间,从各个方面进行测试,但我从未想到这可能是ISP没有使用IPV6。我仍然不明白这是怎么回事。无论如何,添加这两条线路解决了问题。消息传递!
    java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
    java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");