Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


OutputStream.write () éxito pero los datos no se entregan

Tengo un comportamiento muy extraño durante la escritura a un zócalo. En mi cliente móvil estoy utilizando un socket que se inicializa de la siguiente manera:

private void initSocket() { socket = new Socket(); socket.connect(new InetSocketAddress(host, port)); os = new DataOutputStream(socket.getOutputStream()); is = new DataInputStream(socket.getInputStream()); } 

Luego periódicamente (cada 60 segundos) leo y escribo algunos datos a este socket (el código aquí es un poco simplificado):

 if(!isSocketInitialized()) { initSocket(); } byte[] msg = getMessage(); os.write(msg); os.flush(); int bytesAvailable = is.available( ); if(bytesAvailable>0) { byte[] inputBuffer = new byte[bytesAvailable]; int numRead = is.read(inputBuffer, 0, bytesAvailable); processServerReply(inputBuffer, numRead); } 

Y funciona. Pero … A veces (muy infrecuentemente, tal vez 1 o 2 veces al día) mi servidor no recibe datos. Mi registro del cliente tiene el siguiente aspecto:

 Written A Written B Written C Written D Written E 

y así. Pero en el lado del servidor se ve como:

 Received A Received E 

B, C, D registros de datos no fueron recibidos, a pesar de que en el lado del cliente parece que todos los datos fueron enviados sin ninguna excepción!

Tales lagunas pueden ser pequeñas (2-3 minutos) que no es muy malo, pero a veces pueden ser muy grandes (1-2 horas = 60-120 ciclos) y es realmente un problema para mis clientes.

Realmente no tengo ni idea de lo que puede estar mal. Los datos parecen ser enviados por el cliente, pero nunca llega en el lado del servidor. Lo he comprobado también con un proxy.

Sólo tengo registros y no puedo reproducir este problema (pero sucede a mi cliente más de una vez cada día) y en los registros a veces veo que la conexión se rompe con una excepción "sendto falló: ECONNRESET (Conexión restablecida por peer ) ". Después de que el programa cierra el socket, lo reinicializa:

 // close is.close(); os.close(); socket.close(); // reinitialize initSocket(); 

Y trata de escribir los datos de nuevo como se ha descrito anteriormente. Entonces veo el problema: la conexión establecida, la escritura acertada, pero NO DATOS llegó en el servidor!

Puede ser que tiene algo que ver con ECONNRESET puede no ser, pero quiero mencionar esto porque puede ser que es importante.

Estaría muy agradecido por cualquier idea y extremidades.

PS Tal vez desempeña algún papel: el código del cliente se ejecuta en un dispositivo móvil Android que se está moviendo (se encuentra en un coche). La conexión a Internet se establece a través de GPRS.


UPD: ¡Puedo reproducirlo! Al menos parcialmente (el cliente envía A, B, C, D, E y el servidor recibe sólo A). Sucede cada vez si:

  1. La conexión se establece, el cliente lee y escribe -> OK

  2. La conexión se pierde (apago mi enrutador WLAN :)), me convertí en IOException, cierro los arroyos y socket -> OK

  3. Enciendo mi enrutador, la conexión está de vuelta, vuelvo a inicializar el socket, el programa ejecuta write () sin excepciones, pero … no llega ningún dato al servidor.

BTW ya que la conexión está de nuevo disponible () devuelve siempre 0.

  • ¿Usando OKHttp, cuál es la diferencia entre la petición síncrona en AsyncTask y la petición asíncrona de OKhttp?
  • Activar simultáneamente la interfaz wifi y 3G en Android
  • Comunicación punto a punto entre la aplicación móvil y el navegador de PC
  • Utilizar múltiples interfaces de red en una aplicación
  • Cómo reanudar el proceso de carga de archivos en Android?
  • Datos de enlace descendente de la ruta de Android vía WiFi y datos de enlace ascendente a través de la red móvil
  • Pérdida de paquetes mientras recibe la transmisión UDP en el dispositivo android
  • Android (Java) los recursos de programación de red
  • 2 Solutions collect form web for “OutputStream.write () éxito pero los datos no se entregan”

    Deshágase de la prueba available() . Si el par se supone que debe responder, sólo hay que leerlo. De lo contrario, a veces leerá la respuesta y, a veces, no lo hará, y saldrá de sincronía. Hay muy pocos usos correctos de available() , y este no es uno de ellos.

    La causa de este comportamiento extraño era un zócalo no cerrado en el lado del servidor. Podría reproducirlo con pequeño cliente y servidor. Ambos consisten en un par de líneas de código, que hacen lo siguiente:

    1. Conectar con el servidor
    2. Simular un punto muerto (por ejemplo, apagar su WiFi)
    3. Cierre el socket en el lado del cliente
    4. NO CIERRE el socket en el lado del servidor
    5. Enciende tu WiFi
    6. Establecer una nueva conexión desde el cliente
    7. Escribir datos en esta conexión

    Voila! El cliente escribe datos sin errores, pero el servidor no lo recibe …

    Pero si el servidor cierra el socket también, entonces el servidor puede leer estos datos. Así que la solución debe ser cerrar el socket después de un tiempo de espera en el lado del servidor.

    Desafortunadamente en mi caso no es viable, porque el servidor es un software propietario de terceros.

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