Il client finisce di inviare, il proxy vede EOF e la risposta scompare. Chiudere subito entrambi i socket del proxy può causare esattamente questa sequenza. In un relè TCP, una fine ordinata in una direzione non significa che l'altra direzione sia terminata.

Considera un client che invia una richiesta, chiude il proprio lato di invio e attende la risposta:

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

Il proxy ha due connessioni TCP e due flussi di byte che avanzano in modo indipendente. Deve portare avanti l'indicazione di fine dell'input, dopo aver portato i byte che la precedono.

Svuota la coda prima di inoltrare EOF

In una ricezione di dimensione diversa da zero su un flusso TCP, un ritorno di zero indica una fine ordinata di quel flusso in ingresso. Marca quella direzione di lettura come terminata. Smette di attendere altro input da essa, ma conserva i byte già accodati per il socket opposto.

Una volta svuotata la coda da client a servizio, chiama shutdown(service_socket, SHUT_WR) su un socket POSIX. Questo termina l'ulteriore trasmissione verso il servizio lasciando disponibile la direzione da servizio a client. Quando il servizio termina la sua risposta, applica l'operazione speculare dopo aver svuotato la coda della risposta.

La chiusura dei descrittori spetta al momento in cui entrambe le direzioni e i loro buffer in sospeso sono terminati, o in cui un errore o una cancellazione richiedono la chiusura. Mantieni un timeout limitato per un peer che non completa mai la sua metà rimanente.

La prontezza è un invito a leggere

Un socket leggibile può avere dati o una condizione di EOF. Chiama recv e interpreta il risultato. I conteggi positivi sono byte da inoltrare; zero è la fine direzionale. Su un socket non bloccante, EAGAIN o EWOULDBLOCK significano che al momento non c'è altro input, mentre EINTR può richiedere un nuovo tentativo. Nessuno dei due è lo stesso evento di EOF.

Non cercare un flag FIN nel buffer di byte restituito. TCP consegna a questa API un flusso di byte ordinato; i confini dei pacchetti e il segmento FIN non sono normale carico utile dell'applicazione.

Questo è il ciclo di vita di un tunnel di byte grezzo. Un proxy HTTP che analizza i messaggi deve comunque rispettare l'incorniciatura HTTP, e un proxy che termina TLS ha anch'esso un protocollo di chiusura TLS. Mantieni queste decisioni di protocollo sopra il relè TCP direzionale.

Articoli correlati