Il TCP è un protocollo di trasporto che assicura il trasporto affidabile. Mediante TCP è possibile costruire applicazioni che si basano sul trasferimento di file senza errori tra host remoti. Il protocollo TCP effettua anche un controllo di congestione end-to-end che limita il traffico di rete e consente agli utenti di condividere in modo equo le risorse.
TCP è orientato alla connessione, di conseguenza prima di cominciare il trasferimento dati è necessario instaurare una connessione mediante opportuna segnalazione. Inoltre le connessioni TCP si appoggiano su datagram e sono di tipo full-duplex.
Il TCP è orientato alla trasmissione di flussi continue di dati: i flussi sono convertiti in segmenti di dimensione variabile e sono accumulati in un buffer. Periodicamente il TCP prende una parte dei dati nel buffer e forma un segmento. Siccome la dimensione del segmento è critica per le prestazioni TCP cerca di attendere fino a che un ammontare ragionevole di dati non sia presente nel buffer di trasmissione.
Il TCP adotta un meccanismo per il controllo delle perdite di pacchetti di tipo Go-Back-N.
Il TCP numera ogni byte trasmesso, I segmenti sono formati da gruppi di byte. Nell'header TCP è trasportato il numero di sequenza del primo byte, e il ricevitore deve riscontrare i dati ricevuti inviando il numero di sequenza del prossimo byte che ci si aspetta. Se un riscontro non arriva entro un dato timeout, i dati sono ritrasmessi.
Definiamo i contenuti dell'header:
URG
: Vale 1
se vi sono dei dati urgenti e quindi TCP deve passare in modalità urgente.ACK
: Vale 1
se il pacchetto è un ACK valido, cioè se contiene un acknowledge number validoPSH
: Vale 1
quando il trasmettitore intende usare il comando di PUSH: il ricevitore può anche ignorare il comandoRST
: reimposta la connessione senza un tear down esplicitoSYN
: usato durante il setup per comunicare i numeri di sequenza inizialeFIN
: usato per la chiusura esplicita di una connessioneDi seguito alcune opzioni aggiunte:
Definisce la dimensione massima del segmento che verrà usata nella connessione TCP. La dimensione è decisa dal mittente durante la fase di setup. Di default è 536 byte.
Definisce il fattore di scala della finestra. Fa sì che venga moltiplicato il valore del campo Window di un fattore pari a 2 elevato al valore contenuto nel campo fattore di scala. Di default è 1.
SYN
=1 contenente il numero di sequenza. Eventualmente indica anche i parametri aggiuntivi. Il numero casuale serve a evitare problemi nel caso il setup non vada a buon fine.SYN
, il server TCP estrae un numero di sequenza iniziale e manda un segmento SYN
=1 e ACK
=1 contenendo AN
pari al numero estratto dal client.SYN
/ACK
del server e invia ACK
con AN
pari al numero estratto dal server. Inserisce anche la dimensione di finestra del server.ACK
del client, notifica al suo applicativo che la connessione è aperta.FIN
=1 con gli ultimi dati.ACK
per confermare, lasciando comunque la connessione aperta.FIN
=1.ACK
finale.La connessione può essere chiusa senza scambio di messaggio nei due versi, in quanto è possibile semplicemente interrompere la connessione impostando il flag di RESET
.
Il lato TCP ricevente controlla il flusso di quello ricevente. In entrambi i lati esistono dei Buffer che accumulano byte ricevuti/in attesa di essere trasmessi.
Lo spazio del buffer in ricezione disponibile per ricevere nuovi dati è detto RCVWND
, e si estende dall'ultimo byte inoltrato all'applicazione fino alla fine del buffer. Il buffer di ricezione può riempirsi in certi casi. La sua dimensione è segnalata in ogni segmento inviato dal ricevitore al trasmettitore.
Una il buffer di invio è detto SNDWND
e rappresenta i byte che possono essere trasmessi senza attendere ulteriori riscontri. Contiene inoltre la dimensione della finestra di ricezione del partner. Si estende dal primo byte non riscontrato all'estremo a destra della finestra di ricezione del ricevitore.
Questo problema si manifesta sia nel buffer di ricezione che in quello di invio e rallenta la trasmissione.
Nel ricevitore il buffer di ricezione viene svuotato lentamente, di conseguenza i segmenti sono inviati con una finestra molto piccola e il trasmettitore deve inviare segmenti corti con molto overhead.
Nel trasmettitore l'applicazione genera dati lentamente, e quindi invia segmenti molto piccoli man mano che vengono prodotti.
Per evitare la Silly window syndrome nel ricevitore, esso mente al trasmettitore indicando una finestra nulla sino a che il suo buffer di ricezione non si è svuotato per metà o per una porzione almeno pari al MSS:
Per evitare la Silly window syndrome nel trasmettitore, esso invia la prima porzione di dati anche se corta, e gli altri dati vengono inviati solo se il buffer di uscita contiene dati sufficienti a riempire una MMS
oppure, quando si riceve un AN
per un segmento precedente.
TCP originariamente prevedeva una gestione speciale per i dati che richiedono di essere consegnati immediatamente, per ottenere l'invio immediato infatti l'applicazione può impostare il campo PUSH
, anche se generalmente non è disponibile nelle interfacce offerte dai linguaggi di programmazione, infatti è automaticamente impostato nell'ultimo segmento che svuota il buffer.
TCP dispone di una modalità urgent, che però per dei cambiamenti negli standard RFC non è stabile. Gli RFC successivi ribadiscono il cambiamento più recente, tuttavia alcuni dispositivi seguono ancora quello vecchi. Inoltre i sistemi operativi implementano urgent in maniera differente, è consigliabile non usare.
Il meccanismo di controllo d'errore del TCP serve a recuperare pacchetti persi in rete. La causa principale di tale perdita è l'overflow di una delle code dei router attraversati a causa della congestione. I dati vengono ritrasmessi usando Go-Back-N con timeout:
ACK
che riscontra collettivamente anche i segmenti fuori ordine.La finestra di trasmissione dipende dal meccanismo di controllo di flusso e di congestione.
Uno dei problemi è stabilire il valore ottimo del timeout. Il suo valore ottimale dipende fortemente dal ritardo di rete, quindi il TCP calcola dinamicamente un valore opportuno per il timeout stimando il RTT.
Il TCP adatta il timeout di trasmissione alle condizioni reali della rete tramite gli algoritmi di Karn e Jacobson: campioni di RTT sono definiti come il tempo che passa tra la trasmissione di un segmento e la ricezione del relativo riscontro. Quindi tramite l'algoritmo di Jacobson viene calcolato SRR (Smoothed Round Trip Time):
Sulla base di questi valori il timeout è calcolato come
Dopo la ritrasmissione è necessario passare all'algoritmo di Karn:
Se il destinatario fissa a 0 la finestra di ricezione la sorgente TCP interrompe la trasmissione, e riprende solo quando il destinatario invia un ACK
con una dimensione della finestra diversa da 0. Tuttavia se questo ACK
andasse perso la connessione rimarrebbe bloccata.
Per evitare questa situazione si usa un timer di persistenza che viene attivato quando arriva un segmento con finestra nulla. Se il timer di persistenza scade, viene inviato un piccolo segmento sonda, in questo modo se viene ricevuto un ACK
si esce dallo stato critico, altrimenti al nuovo scadere del timeout si re invia di nuovo.
Il controllo di flusso dipende dalla capacità del ricevitore. Tuttavia attualmente non esistono meccanismi di controllo di congestione a livello rete, esso è delegato a TCP e quindi è end-to-end. Il modo più naturale per controllare il ritmo di immissione in rete dei dati per il TCP è quello di regolare la finestra di trasmissione.
Il trasmettitore mantiene una Congestion Window (CWND
) che varia in base agli eventi osservati. Il trasmettitore non può trasmettere più del minimo tra RCVWND
e CWND
: CWND
, quindi riduco il rate equivalente sulla connessione TCP che sto valutando.
Il valore di CWND
viene aggiornato dal trasmettitore TCP in base ad un algoritmo: Il modo in cuoi avviene l'aggiornamento si basa sulla fase del trasmettitore (Slow start e Congestion Avoidance). Lo stato è dettato dalla variabile SSTHRESH
:
CWND
SSTHRESH
si è in Slow Start.CWND
SSTHRESH
si è in Congestion Avoidance.Inizialmente, il trasmettitore pone CWND
a 1 MSS
e la SSTHRESH
a un valore molto elevato, di conseguenza si parte in Slow Start. In questa modalità, la CWND
viene incrementata di 1 per ogni ACK
ricevuto. Al contrario di quanto il nome faccia credere infatti, l'incremento della finestra avviene in modo esponenziale. L'incremento può andare avanti fino a uno di questi eventi:
CWND
SSTHRESH
CWND
RCWND
Insieme alla finestra aumenta anche il rate di trasmissione, che è stimato come
Un evento di congestione si verifica quando il ritmo di trasmissione porta in congestione un link sul percorso in rete verso la destinazione. Un link è definito congestionato quando la somma dei ritmi di trasmissione dei flussi che lo attraversano è maggiore delle sue capacità.
In caso scada il timeout di ritrasmissione il TCP reagisce ponendo SSTHRESH
pari alla metà dei byte trasmessi ma non riscontrati:
Di solito i "byte in volo" sono una buona approssimazione pari all'ultima CWND
. Di conseguenza:
CWND
è minore di SSTHRESH
e si entra nella fase di Slow StartCWND
è incrementata di 1 ad ogni ACK
.A questo punto il trasmettitore trasmette tutti i segmenti a partire da quello per cui il timeout è fallito (Go-Back-N), e il valore a cui è posta SSTHRESH
è una stima della finestra ottimale che eviterebbe futuri eventi di congestione.
La slow start continua fino a che CWND
diventa grande come SSTHRESH
e poi parte la fase di Congestion Avoidance. Durante questa fase si incrementa CWND
di ACK
ricevuto. Se la CWND
consente di trasmettere ACK
relativi a tutti gli CWND
ad aumentare di 1 segmento.
In questa modalità quindi si attua un incremento lineare della finestra di congestione.
È possibile dimostrare che in condizioni ideali il meccanismo di controllo del TCP è in grado di:
Le condizioni ideali sono alterate tra l'altro da:
Questa feature aggiuntiva al TCP classico è usata per ottimizzare la ritrasmissione del singolo pacchetto perso.
Se arrivano degli ACK
duplicati il pacchetto sarà andato perso, tuttavia saranno arrivati i pacchetti successivi. Se non c'è congestione possiamo incrementare CWND
del numero di pacchetti sicuramente arrivati. Grazie a questa feature il trasmettitore trasmette il pacchetto perso dopo il terzo ACK
duplicato:
ACK
consecutivo duplicato: AN
.ACK
duplicato ricevuto la CWND
viene incrementata di 1.CWND
e RWND
.ACK
che riscontra nuovi dati si esce dalla fase di fast recovery e si pone di nuovo: Esistono diverse versioni di TCP, ma sono tutte retrocompatibili con le versioni base. TCP è implementato nel sistema operativo, infatti esistono versioni come ECN che viola la comunicazione tra livelli differenti.
Esistono inoltre versioni adatte a connessioni ibride, dove le perdite sono dovute sia alla congestione che alla perdita sporadica legata a problemi di connessione radio.
La versione base TCP si chiama Tahoe.