¿Por qué DefaultHttpClient envía datos a través de un socket semi-cerrado?

Estoy utilizando DefaultHttpClient con un ThreadSafeClientConnManager en Android (2.3.x) para enviar solicitudes HTTP a un servidor REST (embarcado Jetty).

Después de ~ 200 segundos de tiempo de inactividad, el servidor cierra la conexión TCP con un [FIN]. El cliente de Android responde con un [ACK]. Esto debería dejar el socket en un estado medio cerrado (el servidor sigue escuchando, pero no puede enviar datos).

Espero que cuando el cliente intente usar esa conexión otra vez (vía HttpClient.execute ), DefaultHttpClient detectaría el estado semicerrado, cierre el zócalo en el lado del cliente (así que el enviarlo es [FIN / ACK] para finalizar el cierre) , Y abra una nueva conexión para la solicitud. Pero, está el frotamiento.

En su lugar, envía la nueva solicitud HTTP sobre el socket semi-cerrado. Sólo después del envío se detecta el estado semi-cerrado y se cierra el socket en el lado del cliente (con el [FIN] enviado al servidor). Por supuesto, el servidor no puede responder a la solicitud (ya había enviado su [FIN]), por lo que el cliente cree que la solicitud ha fallado y vuelve a intentar automáticamente a través de un nuevo socket / conexión.

El resultado final es que el servidor ve y procesa dos copias de la solicitud.

¿Alguna idea sobre cómo solucionar este problema? (Mi servidor hace lo correcto con la segunda copia, pero me molesta que la carga útil se transmita dos veces).

¿No debería DefaultHttpClient detectar que el zócalo se cerró cuando primero intenta escribir el nuevo paquete HTTP, cierre ese zócalo inmediatamente, e inicie uno nuevo? Estoy desconcertado en cuanto a cómo una nueva solicitud HTTP se envía en un socket minutos después de que el servidor envió un [FIN].

Esta es una limitación general de la E / S de bloqueo en Java. Simplemente no hay manera de averiguar si el punto final opuesto tiene o no conexión cerrada, aparte de intentar leer desde el socket. Apache HttpClient trabaja este problema con el empleo de la verificación de conexión tan rancio que es esencialmente una operación de lectura muy breve. Sin embargo, el cheque puede ya menudo está inhabilitado. De hecho, a menudo es aconsejable tenerlo inhabilitado debido a la latencia adicional que el cheque introduce. No tengo ni idea de cómo exactamente la versión de HttpClient enviada con Android se comporta a este respecto, pero podría intentar explícitamente habilitar la comprobación mediante un parámetro de configuración adecuado.

Una mejor solución a este problema podría ser desalojar las conexiones del grupo de conexiones que han estado inactivas durante un período de tiempo determinado (digamos 150 segundos) después de un período de inactividad.

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e652

  • React-native-tcp no funciona en Android 7+
  • Obtener la puerta de enlace predeterminada mediante programación utilizando getHostAddress () de la clase InetAddress
  • Comunicación TCP de Android con C # Server -> socket.Close
  • Android: Transferencia de la conexión TCP de 3G a WiFi
  • La pila TCP XBox 360 no responde a sondas TCP Zero Window con una carga útil de 0 bytes
  • El servidor de inicio de adb.exe falló en el estudio de android
  • No se puede conectar Android ADB a TCP / IP
  • ¿Cómo puede un emulador androide ponerse en contacto con la máquina desarrolladora del host en eclipse?
  • Android VpnService, reenvío de paquetes
  • ¿Android 4.x soporta streaming RTSP sobre TCP?
  • Mejores prácticas de la conexión TCP de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.