Pérdida severa de paquetes UDP en algunos dispositivos Android

He limpiado el interwebz sin resultado. Nos enfrentamos a un problema en el que algunos dispositivos Android experimentan pérdida severa de paquetes. Para dar un poco de fondo, la aplicación se conecta a un Wifi específico y busca paquetes UDP emitidos en el puerto 17216. Estos paquetes son de tamaño 832 bytes, excluyendo los encabezados envueltos, y se envían a una velocidad regular de cuatro por segundo.

Sólo hemos encontrado el problema en dos dispositivos, una tableta Turbo Rubik II de gama baja y una Memo Pad HD 7 de ASUS. Los otros dispositivos que hemos probado (teléfonos y tabletas) recogen todos los paquetes en el intervalo regular estipulado.

La función que recibe los paquetes es la siguiente:

public void run() { while (isUDPServerRunning) { try { socket.receive(packet); ProcessRawPacketData(); DisplayLoggingInfo(); } catch (IOException e) { Log.e("receive", e.getMessage()); e.printStackTrace(); } } } 

Y eso es parte de un Runnable . El socket se crea así:

 byte[] buffer = new byte[1024]; DatagramSocket socket; DatagramPacket packet = new DatagramPacket(buffer, buffer.length); 

Con el zócalo inicializado en el método onCreate() de nuestra extensión de Service :

 socket = new DatagramSocket(SERVERPORT); 

Los paquetes están siendo recibidos por el módulo Wifi. Hemos confirmado que mediante el enraizamiento de uno de los dispositivos y la instalación de un rastreador de paquetes, por lo que el problema debe ser de alguna manera relacionados con el código.

En los dispositivos afectados los paquetes se reciben correctamente durante un par de segundos y luego hay un abandono completo que dura varios segundos, por lo que estimo que la pérdida supera el 50%.

Cualquier ayuda sería muy apreciada. Estamos sacando nuestro pelo.

Actualización que estaba equivocado sobre el paquete sniffer. Parece que el rastreador de paquetes también está perdiendo varios paquetes relevantes en el dispositivo enraizado. A veces , sin embargo, simplemente iniciar el sniffer de paquetes arregla el problema! Activar / desactivar Bluetooth como se sugiere a continuación no parece hacer la diferencia. ¿Podría ser esto otro problema de hardware?

Actualización 2 Aquí hay un ejemplo de los registros que estoy imprimiendo inmediatamente después de la línea socket.receive() . Observe cómo se salta medio minuto de paquetes y luego funciona bien durante unos segundos.

 05-25 15:44:38.670: D/LOG(4393): Packet Received 05-25 15:44:38.941: D/LOG(4393): Packet Received 05-25 15:45:09.482: D/LOG(4393): Packet Received 05-25 15:45:09.716: D/LOG(4393): Packet Received 05-25 15:45:09.928: D/LOG(4393): Packet Received 05-25 15:45:10.184: D/LOG(4393): Packet Received 05-25 15:45:10.451: D/LOG(4393): Packet Received 05-25 15:45:10.661: D/LOG(4393): Packet Received 

La pérdida de paquetes (como usted sabe, por supuesto) puede suceder en múltiples etapas a lo largo de la transmisión:

  1. Envío desde el servidor
  2. Transmisión a través de la red
  3. Recepción física en el cliente y manejo en hardware
  4. Procesamiento / almacenamiento en memoria intermedia del paquete en el kernel / OS
  5. Manejo / almacenamiento en búfer del paquete en su aplicación.

Puede comprobar rápidamente si el punto 1 o 2 es un problema al tener otros dispositivos que escuchan la misma emisión mientras están conectados al mismo enrutador Wifi. Parece que ya has hecho esto y que no hay problema. (Tenga en cuenta que un paquete que se deja caer en el paso 2 (oa veces incluso 1) no puede faltar en el volcado de WireShark si lo ejecuta en el servidor).

Por lo tanto, los puntos 3 a 5 pueden ser el problema y podrían ser un poco más difíciles de separar.

Aquí hay un par de cosas que podrían ayudar:

  • Como sugirió @Mick, no sólo imprima cuando recibió el paquete, sino que le dio a cada paquete un número de identificación creciente para averiguar si realmente perdió un paquete o si sólo se retrasó.
  • Mueva su código de recepción de paquetes a su propio hilo (si aún no lo está) y establezca la prioridad de ese hilo en MAX_PRIORITY para minimizar la posibilidad de que su código contenga la línea de almuerzo. Dado que el Memo Pad es una máquina quad-core de 1,2 GHz, MAX_PRIORITY no debería ser necesario, pero si no está ejecutando el loop de recepción en su propio hilo dedicado, es posible que vea hick-ups de todos modos. Si esto arregla las cosas, simplemente tenga un mínimo de recibir-lazo de palo los paquetes en su propia cola de búfer y tienen un proceso de hilo independiente de ellos.
  • Compruebe / aumente el tamaño del búfer de paquetes para recibir paquetes a través de setReceiveBufferSize (…) ( una referencia más detallada de Java aquí ). Asegúrese de especificar un tamaño que puede contener muchos paquetes. Teniendo en cuenta que ejecutar el sniffer de paquetes a veces parece ayudar a las cosas, parece que puede haber algún ajuste de socket que puede mejorar las cosas, que el sniffer pasa a establecer.
  • En el servidor también puede agregar una etiqueta al paquete que indica a todos los dispositivos involucrados cómo tratar el paquete. Si llama a setTrafficClass (IPTOS_RELIABILITY) , está pidiendo a todos los involucrados que optimicen su manejo de paquetes para obtener la máxima fiabilidad. No todos los dispositivos se preocupan, pero puede hacer una diferencia.
  • Puede intentar utilizar DatagramChannels en lugar de DatagramSockets y, a continuación, utilice select () para esperar a que el siguiente paquete lea. Aunque esto técnicamente no debería marcar la diferencia, a veces, el uso de una llamada de API diferente puede proporcionar una solución para un problema.
  • Lamentablemente, Android es un entorno muy heterogéneo en el que muchos fabricantes proporcionan sus propios módulos de núcleo, etc. Esto también introduce diversas incompatibilidades o comportamiento no estándar en todas partes. Es posible que pueda encontrar una ROM personalizada (Cyanogen, etc.?) Para uno o ambos de sus dispositivos problemáticos. Si la instalación que en lugar de la ROM de fábrica corrige su problema, entonces es un error en los controladores de red suministrados por el fabricante (núcleo), en cuyo caso, podría tener suerte para encontrar un trabajo alrededor, o tal vez podría presentar un informe de error Con ellos, pero en general, sólo tendrás que seleccionar los dispositivos como no compatibles en Play Store para evitar malos comentarios …

Por último, aquí hay un trabajo que debe arreglar el problema:

Agregue algo de código a su cliente que detecte paquetes perdidos y, si la tasa de abandono es demasiado alta, abre una conexión TCP al servidor, lo que garantiza la entrega de paquetes. Dado que sus paquetes son pequeños e infrecuentes y que sólo unos pocos dispositivos necesitarán usar este mecanismo, no creo que esto debería causar un problema para su carga de servidor. Si no tiene una manera de cambiar el código del servidor para proporcionar una secuencia TCP, podría escribir un servidor proxy independiente que recopile los paquetes UDP y los haga disponibles a través de TCP. Si puede ejecutarlo en la misma máquina que el servidor original, incluso sabe en qué dirección IP está (igual que la dirección de origen de los paquetes UDP que llegaron).

Sólo una suposición salvaje, pero ¿cuánto tiempo toman sus cálculos en el paquete? ¿Es posible que el búfer asignado para el socket se llene y empiece a soltar los paquetes?

Lo sé, esto suena poco probable para una tasa de transferencia de alrededor de 4 KB / s … Pero si sus cálculos tardan más de 250 ms que esto ocurriría tarde o temprano. Esto también explicaría por qué algunos dispositivos funcionan como un encanto, y otros no.

¿Ha intentado eliminar los cálculos y acaba de imprimir el mensaje "paquete recibido" para la depuración?

Curiosamente, ambos dispositivos que están experimentando la pérdida de paquetes UDP tienen Mediatek SoCs. ¿Sus otros dispositivos de prueba tienen este mismo chipset?

Esto puede ser un error en el controlador para el Wi-Fi de los SoCs. Siendo que sólo aparece con UDP, y no siempre es 100%, puede haber sido desapercibida por todos hasta ahora.

Esto suena muy similar a los síntomas de la interferencia de Bluetooth que se pueden ver en Android (e iOS – de hecho cualquier cosa con WiFi y Bluetooth juntos) dispositivos.

2.4Ghz WiFi y Bluetooth comparten el mismo ancho de banda y pueden interferir entre sí – en algunos dispositivos esto es muy pronunciado, tal vez debido a la disposición interna.

También es posible que pueda verlo en algunos dispositivos y no en otros debido a las versiones de WiFi que soportan: el nuevo WiFi basado en 5GHz no interfiere con el bluetooth de la misma manera, pero algunos dispositivos Android más antiguos o más básicos pueden no ser compatibles esta.

Usted puede probar si esto es la causa con bastante facilidad apagando bluetooth en el dispositivo durante la prueba (si su aplicación puede funcionar sin bluetooth).

  • Aplicación de chat: qué tecnología es mejor para implementar aplicación de chat en Android
  • Cliente Android / socket de servidor Java; Android enviar pero no recibir?
  • Sockets, Threads y Servicios en android, ¿cómo hacerlos trabajar juntos?
  • Comunicación con Java socket de Android con Socket.IO
  • Socket para servidor Android
  • Enviar / Recibir archivo / imagen Socket C # Android
  • Android socket de programación ... ¿qué da?
  • HTTP Vs sockets Vanilla para cargar archivos binarios grandes (50-200 MB) desde un dispositivo Android a través de una red Wi-Fi de un solo salto
  • UDP Multicasting desde el móvil a la PC
  • Conexión de dos teléfonos Android para transferir datos entre ellos a través de WIFI
  • Implementación cliente / servidor de socket TCP de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.