java.net.ServerSocket.accept()在Android上不返回

时间:2011-09-01 16:24:41

标签: android sockets telnet

我正在尝试telnet到一个无根的Droid。我已启用INTERNET权限,我通过WiFi将设备连接到与Mac OS X框相同的网络上,并且我能够ping通我打开的端口。

在最初的实验中,我让它在一个有根的测试设备上工作,但我在UI Thread而不是一个单独的线程上运行套接字处理程序。既然我在一个单独的线程上有网络模块,我就无法返回ServerSocket.accept ()。它适用于谷歌版本的android(vanilla),但不适用于三星或索尼爱立信。

当我telnet到它时,我的尝试会超时,logcat不会打印出任何异常或错误。

以下是我的代码的Google代码回购链接:Google-code Repository

我在一个单独的线程上运行ServerScoket.accept (),并在另一个线程上运行流处理器。我的设计评论(即我应该使用HandlerAsyncTasks)非常受欢迎。现在,为了向通过telnet接收的消息进行Toast,我使用Handler,通过Context获取looper。

以下是我在非工作设备上的adb shell上运行netstat -n时得到的结果:

~$ adb shell netstat -n
Proto Recv-Q Send-Q Local Address          Foreign Address        State
tcp        0      0 127.0.0.1:7777         0.0.0.0:*              LISTEN
tcp        0      0 127.0.0.1:7203         0.0.0.0:*              LISTEN
tcp        0      0 127.0.0.1:47609        127.0.0.1:7777         ESTABLISHED
tcp        0      0 127.0.0.1:7777         127.0.0.1:47609        ESTABLISHED
tcp        0      0 127.0.0.1:47610        127.0.0.1:7777         ESTABLISHED
tcp        0      0 127.0.0.1:7777         127.0.0.1:47610        ESTABLISHED

不同之处在于,在工作设备中,他们列出了一个IP,我的端口在状态LISTEN中打开。

更新:在<uses-permission android:name="INTERNET"/>设置android_manifest后,我尝试将端口号更改为689。它不起作用;我得到了BindException,说我可能缺少INTERNET权限。所以,我将其更改为1989,然后我回到accept ()工作的所有内容。我认为这是因为我在非root手机上运行它,而且我无法访问端口1024及以下。

更新:我在Mac上运行了一个非常类似的程序,当我尝试使用分配给我的IP地址远程登录Mac时,它运行正常。当我尝试从另一台Mac上进行远程登录但它似乎无法连接时,它无法正常工作;连接会超时。但它确实在ad-hoc网络上工作。我还没有尝试使用机器人,但我会尽快更新。

更新:我设法让应用程序在3个独立的Droids上运行Vanilla(由谷歌发布的Android)。它适用于Nexus,Apanda A60(我的第一台设备; adb因某种原因不再检测它),以及定制的无品牌平板电脑。尽管如此,因为我已经提供了相当大的赏金,我计划直到最后才看到它。

如前所述,我的应用程序适用于Android的Vanilla版本,但不适用于修改版本。未能运行它的三部手机都是中档机型; 2 Samsung GT-i5503 s和Sony-Ericcson E16i

3 个答案:

答案 0 :(得分:1)

查看adb shell中的netstat -n是否显示在accept()未返回时您选择的端口上实际侦听的任何内容。

同时意识到,当不以root用户身份运行时,您只能绑定非特权端口,其中默认的telnet端口不是示例。您的代码是否检查bind()是否成功?

更新:

由于代码可以在许多设备上运行(netstat -n可能会列出套接字),因此无法在主题设备上列出它应该仍然是一个焦点。 Java ServerSocket方法依赖于套接字工厂,它可以被覆盖以允许您对socket(),bind()和listen()进行不同的调用,从而指定更全面的细节,因此以这种方式尝试代码可能是有意义的。还有一个案例浮出水面,设备试图支持ipv6似乎导致了类似的问题,至少在其他java平台上创建低级别的套接字以指定ipv4似乎是一个很有希望的答案。

答案 1 :(得分:1)

您似乎遇到了网络问题,而不是代码问题。我使用了你的最新项目,正如预期的那样正在监听端口。

我将此添加到TelnetServer.setupServerSocket()以确认一些信息:

Log.i("TelnetServer", "ServerSocket Address: " + this.server.getLocalSocketAddress());
try {
    Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
    while (en.hasMoreElements()) {
        NetworkInterface intf = en.nextElement();
            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                InetAddress inetAddress = enumIpAddr.nextElement();
                Log.i("TelnetServer", "Listen On: " + inetAddress.getHostAddress());
            }
        }
} catch (SocketException ex) {
    Log.e("TelnetServer", ex.toString(), ex);
}

这将打印您的服务正在侦听的所有地址(如果它正在侦听0.0.0.0/0.0.0.0:xxx(在ServerSocket地址之后打印))。

您应该使用emulator选项运行-tcpdump <file>并提供此选项。它将确认正在尝试任何连接。我的预感是你的客户端无法访问服务器,这就是服务器没有收到连接的原因 - 而不是代码的问题。

请提供tcpdump文件,您的IP地址(客户端)和logcat输出(包括ServerSocket地址和Listen On语句)以供进一步分析。

答案 2 :(得分:0)

我知道你已经尝试了大部分的事情,你只需几步就可以在两个特定的设备上使用它。

只是一个想法,如果不是点到点,为什么不在地区网络中使用Muti-casting进行服务注册和发现。

这是java实现JmDNS

这是Android demo

编辑:我应该说要检查与这两个设备的连接。