¿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).
- Cómo configurar el tiempo de espera keepalive en Android?
- Android: Transferencia de la conexión TCP de 3G a WiFi
- Comunicación TCP de Android con C # Server -> socket.Close
- Cliente Android y servidor Java Comunicación TCP
- ¿Por qué estoy enviando un RST si mi socket está conectado y no cerrado?
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].
- Exponiendo puertos en Android con React-Native
- React-native-tcp no funciona en Android 7+
- No se pudo conectar a tcp: 5037: no se puede conectar a 127.0.0.1:5037: No se pudo establecer conexión porque la máquina de destino lo rechazó activamente. (10061)
- ¿Cómo puedo mantener mi aplicación en segundo plano?
- No se puede usar ServerSocket en Android
- Escritura de audio en el servidor a través de un socket TCP
- Reutilizar conexiones TCP con HttpsUrlConnection
- Tcp conexión otro dispositivo android, basado en # teléfono en lugar de IP?
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
- Desconexión del dispositivo BLE con el dispositivo Android automáticamente. Android BLE
- Problema extraño al realizar la transición de ImageView en Android 5.0