Encaminhar o meio-fecho TCP depois de drenar os bytes pendentes
Trate EOF num proxy TCP sem descartar dados em fila nem cortar a resposta na outra direção.
O cliente termina de enviar, o proxy vê EOF e a resposta desaparece. Fechar ambos os sockets do proxy imediatamente pode causar exatamente essa sequência. Num relé TCP, um fim ordenado numa direção não significa que a outra direção tenha terminado.
Considere um cliente que envia um pedido, encerra o seu lado de envio e espera a resposta:
client -- request, then FIN --> proxy --> service
client <-------- reply ------- proxy <-- service
O proxy tem duas ligações TCP e dois fluxos de bytes que avançam de forma independente. Tem de levar a indicação de fim de entrada mais adiante, depois de levar os bytes que a precedem.
Esvazie a fila antes de encaminhar EOF
Numa receção de tamanho diferente de zero num fluxo TCP, um retorno de zero indica um fim ordenado desse fluxo de entrada. Marque essa direção de leitura como terminada. Deixe de esperar mais entrada dela, mas conserve os bytes já em fila para o socket oposto.
Quando a fila de cliente para serviço estiver vazia, chame shutdown(service_socket, SHUT_WR) num socket POSIX. Isso termina a transmissão posterior para o serviço e deixa disponível a direção de serviço para cliente. Quando o serviço terminar a sua resposta, aplique a operação espelhada depois de esvaziar a fila de resposta.
O fecho dos descritores pertence ao ponto em que ambas as direções e os seus buffers pendentes estão terminados, ou em que um erro ou cancelamento exige terminação. Mantenha um tempo limite limitado para um par que nunca completa a sua metade restante.
A disponibilidade é um convite a ler
Um socket legível pode ter dados ou uma condição de EOF. Chame recv e interprete o resultado. Contagens positivas são bytes a encaminhar; zero é o fim direcional. Num socket não bloqueante, EAGAIN ou EWOULDBLOCK significam que neste momento não há mais entrada, enquanto EINTR pode exigir nova tentativa. Nenhum dos dois é o mesmo evento que EOF.
Não procure um sinalizador FIN no buffer de bytes devolvido. O TCP entrega a esta API um fluxo de bytes ordenado; os limites de pacote e o segmento FIN não são carga útil normal da aplicação.
Este é o ciclo de vida de um túnel de bytes em bruto. Um proxy HTTP que analisa mensagens continua a ter de respeitar o enquadramento HTTP, e um proxy que termina TLS também tem um protocolo de encerramento TLS. Mantenha essas decisões de protocolo acima do relé TCP direcional.