El cliente termina de enviar, el proxy ve EOF y la respuesta desaparece. Cerrar ambos sockets del proxy de inmediato puede provocar exactamente esa secuencia. En un relé TCP, un final ordenado en una dirección no significa que la otra dirección haya terminado.

Considere un cliente que envía una solicitud, cierra su lado de envío y espera la respuesta:

client -- request, then FIN --> proxy --> service
client <-------- reply ------- proxy <-- service

El proxy tiene dos conexiones TCP y dos flujos de bytes que avanzan de forma independiente. Debe llevar la indicación de fin de entrada hacia delante, después de llevar los bytes que la preceden.

Vacie la cola antes de reenviar el EOF

En una recepción de tamaño distinto de cero en un flujo TCP, un retorno de cero indica un final ordenado de ese flujo entrante. Marque esa dirección de lectura como terminada. Deje de esperar más entrada de ella, pero conserve los bytes ya encolados para el socket opuesto.

Una vez vaciada la cola de cliente a servicio, llame a shutdown(service_socket, SHUT_WR) en un socket POSIX. Eso termina la transmisión posterior hacia el servicio y deja disponible la dirección de servicio a cliente. Cuando el servicio termina su respuesta, aplique la operación simétrica tras vaciar la cola de respuesta.

Cerrar los descriptores corresponde al punto en que ambas direcciones y sus búferes pendientes han terminado, o en que un error o una cancelación exigen terminar. Mantenga un tiempo de espera acotado para un par que nunca completa su mitad restante.

La disponibilidad es una invitación a leer

Un socket legible puede tener datos o una condición de EOF. Llame a recv e interprete su resultado. Los recuentos positivos son bytes que reenviar; cero es el final direccional. En un socket no bloqueante, EAGAIN o EWOULDBLOCK significan que ahora no hay más entrada, mientras que EINTR puede exigir reintentar. Ninguno de los dos es el mismo evento que EOF.

No busque un indicador FIN en el búfer de bytes devuelto. TCP entrega un flujo de bytes ordenado a esta API; los límites de paquete y el segmento FIN no son carga útil normal de la aplicación.

Este es el ciclo de vida de un túnel de bytes sin procesar. Un proxy HTTP que analiza mensajes sigue teniendo que respetar el enmarcado HTTP, y un proxy que termina TLS también tiene un protocolo de cierre TLS. Mantenga esas decisiones de protocolo por encima del relé TCP direccional.

Artículos relacionados