Java.net.ServerSocket.accept () no vuelve en Android

Estoy tratando de hacer una manera de telnet a un Droid unrooted. Tengo el permiso de INTERNET activo, tengo mi dispositivo conectado en la misma red que mi caja de Mac OS X vía WiFi, y puedo hacer ping al puerto que abrí.

En los experimentos iniciales, lo hice funcionar en un dispositivo de prueba arraigado, pero tenía los controladores de socket ejecutados en el UI Thread lugar de un hilo independiente. Ahora que tengo los módulos de red en un hilo separado, no puedo obtener ServerSocket.accept () para volver. Funciona en la versión de Google de Android (vainilla), pero no en Samsung o Sony-Ericsson.

Cuando hago telnet, mi intento se logcat , y logcat no imprimiría ninguna excepción o error.

Aquí hay un enlace a un repo de código de google de mi código: Google-code Repository

Estoy ejecutando ServerScoket.accept () en un hilo separado, y ejecutar los procesadores de flujo en otro hilo también. Comentarios sobre mi diseño (es decir, debo utilizar Handler s o AsyncTasks ) son muy bienvenidos. En este momento, con el fin de brindar los mensajes recibidos a través de telnet, yo uso un controlador con el looper que se adquiere a través de un Context .

Lo siguiente es lo que obtengo cuando ejecuto netstat -n en el shell de adb en los dispositivos que no funcionan:

 ~$ 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 

La diferencia es que en los dispositivos de trabajo, listan una IP con mi puerto abierto en el estado, ESCUCHAR.

ACTUALIZACIÓN : Teniendo el <uses-permission android:name="INTERNET"/> establecido en mi android_manifest , intenté cambiar el número de puerto a 689 . No funcionó; Tengo un BindException , diciendo que puede ser que me falta el permiso de Internet. Así, lo cambié a 1989 , y volví a todo funcionando hasta accept () . Supongo que esto es porque lo corrí en un teléfono no root, y no tengo acceso a los puertos 1024 y siguientes.

ACTUALIZACIÓN : He ejecutado un programa muy similar en mi Mac, y funcionó bien cuando intenté telnetting a mi Mac usando la dirección IP asignada a mí. No funcionó cuando intenté telnetting de otro Mac pero no parecía conectar; La conexión de tiempo de espera. Sin embargo, funcionó sobre una red ad-hoc. Todavía tengo que probarlo usando el droide, pero lo actualizaré lo antes posible.

ACTUALIZACIÓN : Me las arreglé para conseguir que la aplicación funcione en 3 Droides separados que ejecutan Vanilla (Android lanzado por google). Funcionó en un Nexus, un Apanda A60 (mi primer dispositivo, el adb ha dejado de detectarlo por alguna razón) y una tableta personalizada sin marca. Sin embargo, porque ya he ofrecido una recompensa bastante grande, planeo ver esto hasta el final.

Como se dijo anteriormente, mi aplicación funciona con versiones de Android de Android, pero no con versiones modificadas. Los tres teléfonos que no funcionaban eran modelos de gama media; 2 Samsung GT-i5503 s, y un Sony-Ericcson E16i .

Parece que tienes un problema de red, en lugar de un problema de código. He utilizado su último proyecto y está escuchando en el puerto, como se esperaba.

He añadido esto a TelnetServer.setupServerSocket() para confirmar alguna información:

 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); } 

Esto imprimirá todas las direcciones de su servicio está escuchando (si está escuchando en 0.0.0.0/0.0.0.0:xxx (impreso después de ServerSocket Dirección :)).

Debe ejecutar emulator con la -tcpdump <file> y también proporcionar esto. Se confirmará cualquier conexión que se está intentando. Mi corazonada es que su cliente no puede tener acceso al servidor, que es porqué el servidor no está recibiendo la conexión – algo que un problema con el código.

Proporcione el archivo tcpdump, su dirección IP (del cliente) y la salida logcat (incluyendo las instrucciones ServerSocket Address y Listen On) para un análisis más detallado.

Compruebe si netstat -n del shell de adb muestra algo que realmente escucha en el puerto que eligió en el momento en que accept () no está devolviendo.

También darse cuenta de que cuando no se ejecuta como root, sólo puede enlazar los puertos no privilegiados, de los cuales el puerto telnet por defecto no es un ejemplo. ¿Su código comprueba que bind () tuvo éxito?

ACTUALIZAR:

Dado que el código funciona en varios dispositivos (donde netstat -n probablemente lista el socket), el hecho de no listarlo en el dispositivo sujeto probablemente debería seguir siendo un foco. Los métodos Java ServerSocket dependen de una fábrica de zócalos que puede ser sobrecargada para hacer llamadas distintas a socket (), bind () y listen () especificando detalles más completos, por lo que puede tener sentido probar su código de esa manera. Hay otro caso flotando alrededor de donde el intento de un dispositivo para apoyar ipv6 parece estar causando problemas similares, y al menos en otras plataformas java que crean el socket en un nivel inferior para especificar ipv4 parece una respuesta prometedora.

Entiendo que usted ha intentado la mayoría de las cosas es usted es apenas algunos pasos de conseguirlo derecho en dos dispositivos particulares.

Sólo un pensamiento, si no punto a punto, ¿por qué no utilizar muti-casting para el registro de servicios y el descubrimiento en las redes de área local.

Esta es la implementación java JmDNS

Y esta es su demo de Android

EDIT: Más bien debería decir para comprobar la conectividad con los dos dispositivos.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.