Passa al contenuto principale

Un errore comune è quello di ritenere che il protocollo TCP garantisca la consegna dei dati. In realtà, il protocollo TCP garantisce solo che i dati vengano consegnati allo stack TCP dell'host ricevente o che venga segnalato un errore all'applicazione mittente. Purtroppo, la segnalazione di errore non indica la quantità di dati effettivamente consegnati. Esiste inoltre una differenza significativa tra lo stack TCP ricevente e l'applicazione ricevente.

Esistono due scenari di errore fondamentali. Nel primo, lo stack TCP di invio non riceve i riconoscimenti TCP per i dati che sta trasmettendo. In questo scenario, l'applicazione di invio può continuare a chiamare send per inserire altri dati nel buffer di invio dello stack TCP. Una volta che lo stack TCP ha superato il timeout della trasmissione, il successivo invio (o ricezione) chiamato dall'applicazione di invio indicherà l'errore ETIMEDOUT. L'applicazione ora sa che c'è stato un problema, ma non ha idea di quanti dati siano stati trasmessi con successo. Il successo significa che lo stack TCP di invio ha ricevuto un riconoscimento per i dati dallo stack TCP di ricezione.

Nel secondo scenario, lo stack TCP mittente trasmette i dati e riceve un reset invece di un riconoscimento. Il reset può indicare che lo stack TCP ricevente ha chiuso il socket o che un dispositivo di rete, forse un firewall, è andato in timeout. La volta successiva che l'applicazione mittente chiama send (o receive), viene segnalato l'errore ECONNRESET. Si potrebbe pensare che in questo scenario l'applicazione di invio possa dedurre che solo i dati dell'ultima chiamata di invio abbiano avuto esito negativo, ma non è così. È possibile che lo stack TCP di invio abbia bufferizzato i dati di più chiamate di invio in un unico segmento TCP e che tale segmento abbia attivato il reset, oppure che una serie di segmenti TCP sia stata inviata prima che il reset, attivato dal primo segmento della serie, tornasse al mittente. Tutto ciò che l'applicazione di invio può dedurre è che non tutti i dati sono stati trasmessi con successo.

Esiste un terzo scenario di errore che non ha nulla a che vedere con lo stack TCP (invio o ricezione) o con la rete. Supponiamo che l'applicazione ricevente abbia un bug che le impedisce di leggere i dati. Lo stack TCP ricevente continuerà a ricevere i dati e a inviare conferme TCP fino al momento in cui il buffer di ricezione TCP si riempirà. Tuttavia, ciò può comportare fino a 64K byte di dati (o più se è supportato il ridimensionamento della finestra TCP). Se l'applicazione ricevente deve essere riavviata, tutti i dati nel buffer di ricezione TCP andranno persi. Lo stack TCP ricevente dovrebbe (ma potrebbe non farlo) inviare un reset allo stack TCP mittente quando l'applicazione ricevente viene terminata. Invierà un reset la prossima volta che riceverà un segmento per la connessione ora chiusa. Dal punto di vista dell'applicazione di invio, questo è simile al secondo scenario. Tuttavia, sottolinea che anche se lo stack TCP di ricezione riconosce i dati, in caso di errore, non è sicuro per il mittente presumere che l'applicazione di ricezione abbia letto i dati.

L'idea da trarre da questi scenari di errore è che, senza un riconoscimento a livello di applicazione, un timeout di trasmissione o un errore di reset indicano che alcuni, o forse tutti, i dati trasmessi potrebbero non essere stati letti dall'applicazione ricevente. Per questo motivo raccomando che tutte le applicazioni includano riconoscimenti a livello di applicazione, siano pronte a ristabilire una connessione e a ritrasmettere i dati non riconosciuti e siano in grado di gestire i dati duplicati, poiché ciò che potrebbe essere andato perso è il riconoscimento.