CAPITOLO 5
Il Transmission Control Protocol
Il servizio di trasporto di stream ( TCP )
Il protocollo di controllo della trasmissione ( Trasmission Control Protocol: TCP ) definisce un servizio fondamentale fornito da un' internet, e precisamente la consegna affidabile delle stream. Il TCP fornisce una connessione full-duplex fra due macchine, rendendo possibile lo scambio efficiente di grandi volumi di dati fra le stesse. Poichè impiega un protocollo a finestra scorrevole, il TCP può utilizzare una rete in modo efficiente. Poichè non si riferisce al sottostante sistema di consegna, il TCP è abbastanza flessibile per operare su una grande varietà di sistemi di consegna stessi. Poichè fornisce il controllo di flusso, il TCP consente la comunicazione fra sistemi operanti a velocità notevolmente diverse. L'unità di trasferimento fondamentale impiegata dal TCP è il segmento. I segmenti sono utilizzati per passare informazioni di controllo ( ad esempio, per consentire al software del TCP di due macchine di stabilire connessioni o interromperle ) o di dati. Il formato del segmento permette ad una macchina di trasportare in piggybacking i riscontri dei dati che fluiscono in una direzione, includendo tali riscontri nelle intestazioni dei segmenti di dati che fluiscono nella direziona opposta. Il TCP implementa il controllo di flusso facendo annunciare al ricevitore la quantità di dati che è disposto ad accettare. Il protocollo gestisce anche i messaggi fuori-banda mediante un meccanismo di dati urgenti, nonchè la consegna obbligatoria mediante un meccanismo di spinta. Lo standard attuale del TCP specifica il backoff esponenziale per la ritrasmissione temporizzata ed alcuni algoritmi per evitare la congestione, tra cui la partenza lenta, la riduzione moltiplicativa e l' aumento additivo.
Anche se il TCP è presentato come parte della suite di protocolli TCP/IP, esso è un protocollo indipendente, di applicabilità generale, che può essere adattato per l' impiego con altri sistemi di consegna. Per esempio, poichè il TCP fa pochissime ipotesi sulla rete sottostante, è possibile utilizzarlo in una singola rete, come un' Ethernet, come pure in un' internet complessa. In efetti, il TCP è stato così popolare che uno dei protocolli di sistemi aperti dell' ISO, il TP-4 è un suo derivato.
Al livello più basso, le reti di comunicazione fra computer provvedono alla consegna non affidabile dei pacchetti. I pacchetti possono essere persi o distrutti quando gli errori di trasmissione interferiscono nei dati, quando l' hardware della rete subisce un guasto, o quando il carico della rete diventa così gravoso da superarne la capacità. Le reti che instradano dinamicamente i pacchetti possono gestirli disordinatamente, o dopo un sostanziale ritardo, o fornire dei duplicati. Inoltre, le sottostanti tecnologie di rete possono imporre una dimensione ottimale del pacchetto o porre altri vincoli necessari per ottenere velocità di traferimento efficienti.
Al livello più alto, i programmi applicativi spesso devono trasferire grandi volumi di dati da un computer ad un altro. L' impiego di un sistema di consegna non affidabile e senza connessione per inviare grandi volumi di dati ben presto diventa tedioso e richiede ai programmatori d' incorporare in ciascun programma applicativo le apposite procedure di rilevazione e recupero degli errori. Poichè è difficile progettare, comprendere o modificare il software che provvede correttamente all' affidabilità, sono pochi i programmatori che hanno il necessario bagaglio di conoscenze tecniche. Di conseguenza, un obbiettivo della ricerca sui protocolli di rete è stato quello di trovare delle soluzioni generali ai problemi di fornire un servizio affidabile di consegna delle stream, offrendo agli esperti la possibilità di realizzare un singolo blocco software di protocollo di stream utilizzabile da tutti i programmi applicativi. La disponibilità di un singolo protocollo di applicabilità generale contribuisce ad isolare i programmi applicativi dai dettagli del networking, e rende possibile la definizione di un' interfaccia uniforme per il servizio di trasferimento di stream.
L' interfaccia tra i programmi applicativi ed il servizio di consegna affidabile del TCP/IP può essere descritta da cinque caratteristiche:
Orientamento alla stream: Quando due programmi applicativi ( processi di utente ) trasferiscono grandi volumi di dati, che sono immaginati come stream ( sequenze, o serie ) di bit, suddivise in ottetti o byte di otto bit. Il servizio di consegna delle stream nella macchina di destinazione passa al ricevitore esattamente la medesima sequenza di ottetti che il trasmettitore ha passato al suddetto servizio nella macchina di provenienza.
Connesione di circuito virtuale: Un trasferimento di stream è analogo ad una chiamata telefonica. Prima di poter iniziare il trasferimento, i programmi applicativi trasmittente e ricevente devono interagire coi rispetivi sistemi operativi, informandoli del desiderio di un trasferimento di stream. Concettualmente, una macchina effettua una chiamata che dev' essere accettata dall' interlocutore. I moduli software del protocollo nei due sistemi operativi comunicano inviando dei messaggi attraverso un' internet, verificando che il trasferimento sia autorizzato e che entrambe le parti siano pronte. Una volta che tutti i dettagli sono stati definiti, i moduli del protocollo informano i programmi applicativi che una connessione è stata stabilita e che il trasferimento può iniziare. Durante il trasferimento, il software del protocollo nelle due macchine mantiene la comunicazione per verificare che i dati siano ricevuti correttamente. Se la comunicazione fallisse per un qualsiasi motivo ( ad esempio, per guasto nell' hardware della rete lungo il percorso fra le due macchine), entrambe le macchine rileverebbero il fallimento e ne informerebbero gli rispettivi programmi applicativi. Per descrivere tali connessioni, si userà il termine circuito virtuale, poichè, nonostante i programmi applicativi vedano la connessione come un circuito hardware dedicato, l' affidabilità non è altro che un' illusione provocata dal servizio di consegna delle stream.
Trasferimento bufferizzato: I programmi applicativi inviano una stream di dati attraverso il circuito virtuale passando ripetutamente ottetti di dati al software del protocollo. Quando si trasferiscono i dati, ogni applicazione impiega qualsiasi dato ritenga conveniente, che può essere anche un solo ottetto. All' estremità ricevente, il software del protocollo consegna gli ottetti di stream di dati esattamente nel medesimo applicativo ricevente non appena sono stati ricevuti e verificati. Il software del protocollo è libero di suddividere la stream in pacchetti indipendenti dal programma applicativo. Per rendere più efficiente il trasferimento e per minimizzare il traffico nella rete, di solito le implementazioni raccolgono abbastanza dati da una stream da riempire un datagramma ragionevolmente grande prima di trasmetterlo attraverso un' internet. Quindi, anche se il programma applicativo genera la stream un ottetto alla volta, il trasferimento attraverso un' internet può essere piuttosto efficiente. Similmente, se il programma applicativo sceglie di generare blocchi di dati estremamente grandi, il software del protocollo può scegliere di suddividere ciascun blocco in pezzi più piccoli per la trasmissione. Per quelle applicazioni che lo richiedono, il servizio di stream fornisce un meccanismo di spinta che le applicazioni utilizzano per forzare un trasferimento. All' estremità trasmittente, una spinta obbliga il software del protocollo a trasferire tutti i dati che sono stati generati senza aspettare di riempire un buffer. Quando raggiunge l' estremità ricevente, la spinta fa sì che il TCP renda immediatamente disponibili i dati all' applicazione. Quindi, anche quando la consegna viene forzata, il software del protocollo può scegliere di suddividere la stream in modi inaspettati.
Stream non strutturata: E' importante comprendere che il servizio di stream del TCP/IP non onora le stream di dati strutturate. Per esempio, non c' è alcun modo in cui un' applicazione della contabilità degli stipendi possa richiedere al servizio di stream di contrassegnare i confini tra i record degli impiegati, o per identificare il contenuto della stream come dati di stipendi. I programmi applicativi che utilizzano il servizio di stream devono comprendere il contenuto della stream e concordare sul formato di questa prima di avviare una connessione.
Connessione full-duplex: Le connessioni fornite dal servizio di stream del TCP/IP consentono il trasferimento simultaneo in entrambe le direzioni. Tali connessioni sono dette full-duplex. Dal punto di vista di un processo applicativo, una connessione full-duplex consiste di due stream indipendenti che fluiscono in direzioni opposte, senza alcuna apparente interazione. Il servizio di stream consente ad un processo applicativo di terminare il flusso in una direzione mentre i dati continuano a fluire nella direzione oppposta, rendendo half-duplex la connessione. Il vantaggio di una connessione full-duplex è che il sottostante software del protocollo può inviare in risposta alla provenienza le informazioni di controllo per una stream in datagrammi che trasportano i dati nella direzione opposta. Tale operazione, nota come piggy-backing, contribuisce a ridurre il traffico nella rete.
Affidabilità
Si è detto che il servizio di consegna affidabile delle stream garantisce la consegna di una strem di dati inviata da una macchina ad un' altra senza duplicazione nè perdite. Per far ciò la maggior parte dei protocolli affidabili impiega una sola tecnica fondamentale, nota come riscontro positivo con ritrasmissione. Questa tecnica richiede che un destinatario comunichi con la provenienza, inviando in risposta un messaggio di riscontro ( acknowledgement ) quando ha ricevuto i dati. Il trasmettitore mantiene una registrazione di ciasun pacchetto che invia ed aspetta un riscontro prima di trasmettere il pacchetto successivo. Inoltre, il trasmettitore avvia un timer quando trasmette un pacchetto e ritrasmette quest' ultimo se il timer scade prima che arrivi un riscontro. La seguente figura illustra il modo in cui i dati vengono trasferiti nel più semplice protocollo a riscontro positivo.
Nella figura, gli eventi nel trasmettitore e nel ricevitore sono mostrati rispettivamente a sinistra e a destra. Ogni segmento diagonale con la freccia rappresenta il trasferimento di un messaggio attraverso la rete.
La seconda figura impiega il medesimo tipo di datagramma per mostrare ciò che accade quando un pacchetto viene perso o alterato.
Un protocollo che impiega il riscontro positivo con la ritrasmissione in cui il trasmettitore attende un riscontro per ogni pacchetto inviato.
Tempo scaduto ( timeout ) e ritrasmissione in seguito alla perdita di un pacchetto.
Il trasmettitore avvia un timer quando un pacchetto viene perso o alterato. Quando scade, il trasmettitore pressupone che il pacchetto sia stato perso e lo ritrasmette.
Il problema dell' affidabilità finale sorge quando un sottostante sistema di consegna dei pacchetti duplica un pacchetto. I duplicati possono anche manifestarsi quando le reti sono soggette a lunghi ritardi che causano una ritrasmissione prematura. La risoluzione del problema della duplicazione richiede un' attenta riflessione perchè i pacchetti ed i riscontri possono essere duplicati. Di solito, i protocolli affidabili rilevano i pacchetti assegnando a ciascuno di essi un numero sequenziale e richiedono al ricevitore di ricordare i numeri sequenziali che ha già ricevuto. Per evitare la confusione causata da riscontri ritardati o duplicati, i protocolli di riscontro positivo inviano numeri sequenziali in risposta dei riscontri, affinchè il ricevitore possa associare correttamente quest ultimi.
Prima di esaminare il servizio di stream del TCP è necessario esplorare un ulteriore concetto che stà alla base della trasmissione di stream. Tale concetto noto come finestra scorrevole rende efficiente la trasmissione di stream. Per comprendere l' esigenza delle finestre scorrevoli si riconsideri la sequenza di eventi illustrata nella precedente figura. Per ottenere l' affidabilità il trasmettitore invia un pacchetto e quindi aspetta un riscontro prima di inviarne un altro. I dati viaggiano fra le due macchine in una sola direzione alla volta, anche se la rete è in grado di effettuare la comunicazione in entrambe le direzioni simultaneamente. La rete sarà completamente non operativa durante gli intervalli di tempo in cui le macchine ritardano le risposte ( ad esempio, mentre le macchine determinano i percorsi da seguire o calcolano le checksum ).
La tecnica della finestra scorrevole è una forma più complessa di riscontro positivo e di ritrasmissione di quanto non sia il semplice metodo già discusso. I protocolli a finestra sfruttano meglio la lunghezza di banda della rete perchè consentono al trasmettitore di inviare più pacchetti prima di attendersi un riscontro. Il modo più semplice per raffigurare il funzionamento della finestra a scorrimento consiste nel considerare una sequenza di pacchetti da trasmettere, come mostrato nella successiva figura.
Il protocollo sovrappone una piccola finestra alla sequenza e trasmette tutti i pacchetti che si trovano all' interno di essa.
Si dice che un pacchetto è non riscontrato se è stato trasmesso ma nessun riscontro è stato ricevuto. Tecnicamente, il numero di pacchetti che possono essere non riscontrati in un certo istante è vincolato dalla dimensione della finestra e limitato, ad un certo istante, dalla dimensione della finestra e da un numero piccolo e fisso. Per esempio, in un protocollo a finestra scorrevole la cui dimensione è pari ad otto, al trasmettitore è consentito inviare otto pacchetti prima di ricevere un riscontro.
a ) Un protocollo di finestra scorrevole con otto pacchetti nella finestra.
b ) La finestra scorrevole è disposta in modo tale che il pacchetto 9 può essere trasmesso quando è stato ricevuto un riscontro per il pacchetto 1. Vengono ritrasmessi soltanto i pacchetti non riscontrati.
Come si evince dalla figura prededente, una volta che il trasmettitore ha ricevuto un riscontro per il primo pacchetto all' interno della finestra, esso fa scorrere la finestra ed invia il pacchetto successivo. Essa continua a scorrere fino a che vengono ricevuti dei riscontri.
Le prestazioni dei protocolli a finestra scorrevole dipendono dalla dimensione della finestra e dalla velocità con cui la rete accetta i pacchetti. La seguente figura illustra un esempio di funzionamento del protocollo a finestra scorrevole quando si trasmettono tre pacchetti.
Quando la dimensione della finestra è unitaria, un protocollo a finestra scorrevole coincide col semplice protocollo a riscontro positivo. Aumentando la dimensione della finestra, è possibile eliminare completamente il tempo in cui la rete resta inoperante: cioè, nello stato stazionario, il trasmettitore può inviare dei pacchetti con la stessa velocità con cui la rete li può trasferire.
Concettualmente, un protocollo a finestra scorrevole ricorda sempre i pacchetti che sono stati riscontrati e gestisce un timer distinto per ogni pacchetto non riscontrato. Se un pacchetto viene perso, il timer scade ed il trasmettitore fa scorrere la sua finestra, che si sposta solamente quando tutti i pacchetti sono stati riscontrati. All' estremità ricevente, il software del protocollo gestisce una finestra simile, accettando e riscontrando i pacchetti man mano che arrivano. Quindi, la finestra ripartisce la sequenza di pacchetti in tre insiemi: i pacchetti a sinistra della finestra, che sono stati correttamente trasmessi, ricevuti e riscontrati; i pacchetti a destra, che ancora non sono stati trasmessi; i pacchetti che si trovano dentro la finestra, che sono quelli in fase di trasmissione. Il pacchetto di numero più basso dentro la finestra è il primo pacchetto della sequenza che non è stato riscontrato.
Nella precedente filgura si è presentato un esempio di tre pacchetti trasmessi usando un protocollo a finestra scorrevole. Il concetto fondamentale è che il trasmettitore può inviare tutti i pacchetti nella finestra senza aspettare un riscontro.
Si noti che il trasmettitore invia tutti e tre i pacchetti prima di ricevere un qualsiasi riscontro.
Trasmission Control Protocol ( TCP )
Il TCP è un protocollo di comunicazione e non una porzione di software. La differenza tra un protocollo ed il software che esso implementa è analoga alla differenza tra la definizione di un linguaggio di programmazione ed un compilatore. Il protocollo specifica il formato dei dati e dei riscontri che due computer si scambiano per ottenere un traferimento affidabile, come pure le procedure che i computer utilizzano per garantire che i dati arrivino correttamente. Esso specifica il modo in cui il software del TCP distingue fra più destinazioni in una certa macchina ed il modo in cui le macchine comunicanti effettuano il recupero da condizioni di errore, come la perdita o la duplicazione di pacchetti. Il protocollo specifica anche il modo in cui due computer avviano un trasferimento di stream TCP ed il modo in cui concordano sulla fine di tale trasferimento. Poichè il TCP non pone alcun pressupposto sul sottostante sistema di comunicazione, tale protocollo può essere usato con diversi sistemi di consegna dei pacchetti, tra cui il sistema di consegna di datagrammi IP. Per esempio il TCP può essere implementato per utilizzare le lineee telefoniche commutate, una rete locale, una rete a fibbre ottiche ad alta velocità o una rete geografica di velocità inferiore. In realtà, la grande varietà di sitemi di consegna che il TCP può utilizzare è uno dei suoi maggiori vantaggi.
Come lo User Data Protocol ( UDP ), il TCP risiede al di sopra dell' IP nel modello di statificazione dei protocolli. La seguente figura illustra l' organizzazione concettuale.
La stratificazione concettuale dell' UDP e del TCP. Il TCP fornisce un servizio di stream affidabile, mentre l' UDP fornisce un servizio di consegna dei datagrammi non affidabile.
Il TCP consente la comunicazione simultanea di più programmi applicativi nella stessa macchina e distribuisce fra i vari programmi applicativi il traffico TCP in arrivo. Come l' UDP, il TCP impiega numeri di porta di protocollo per identificare la destinazione finale all' interno di una macchina. Ad ogni macchina è assegnato un piccolo numero intero che serve ad identificarla.
Le porte del TCP sono più complesse perchè un certo numero di porta non corrisponde ad un singolo oggetto. Il TCP definisce un punto terminale come una coppia di numeri interi ( host, porta ) in cui l' host è l' indirizzo IP di un host mentre la porta è una porta TCP di quell' host. Per esempio, il terminale ( 128.10.2.2.25 ) specifica la porta TCP 25 nella macchina il cui indirizzo IP è 128.10.2.3
Dato che la connessione è definita dai suoi due punti terminali, se esiste una comnessione dalla macchina ( 18.26.0.36 ) alla macchina ( 128.10.2.3 ), essa potrebbe essere definita dai punti terminali:
( 18.26.0.36, 1069 ) e ( 128.10.2.3, 25 )
Nel frattempo, un' altra connessione potrebbe essere in corso dalla macchina ( 129.9.0.32 ) nella medesima macchina; si supponga che tale connessione sia identificata dai punti terminali:
( 128.9.0.32, 1184 ) e ( 128.10.2.3, 53 )
Gli esempi di connessione visti finora sono stati semplici perchè le porte utilizzate in tutti i punti terminali erano esclusive. Comunque l' astrazione di connessione consente che un punto terminale sia condiviso da più connessioni. Per esempio si potrebbe aggiungere un' altra connessione alle due elencate sopra con la macchina ( 128.2.254.139 ):
( 128.2.254.139, 1184 ) e ( 128.10.2.3, 53 )
Potrebbe sembrare strano che due connessioni possano utilizzare simultaneamente la porta 53 del TCP nella macchina ( 128.10.2.3 ), ma non c' è ambiguità: poichè il TCP associa i messaggi in arrivo con una connessione anzichè con una porta di protocollo, esso impiega entrambi i punti terminali per identificare la connessione appropriata.
Dal punto di vista del programmatore, l' astrazione di connessione è significativa, in quanto vuol dire si può sviluppare un programma che fornisca un servizio concorrente ( simultaneo ) a più connessioni, senza bisogno di numeri di porta locali esclusivi di ciascuna connessione. Per esempio, la maggior parte dei sistemi fornisce l' accesso concorrente al proprio servizio di posta elettronica, rendendo possibile l' invio simultaneo di posta da parte di più computer. Poichè il programma che accetta la posta in arrivo impiega il TCP per comunicare, esso ha bisogno soltanto di utilizzare una porta locale, pur consentendo il progresso simultaneo di più connessioni.
Diversamente dall' UDP, il TCP è un protocollo orientato alla connessione che richiede che entrambi i punti terminali siano d' accordo nel partecipare: cioè prima che il traffico TCP possa attraversare un' internet, i programmi applicativi alle due estremità della connessione devono concordare sul fatto che tale connessione è stata desiderata. A tal fine, il programma applicativo ad un' estremità esegue una funzione di apertura ( open ) passiva contattando il suo sistema operativo ed indicando che accetterà una connessione in arrivo. In quell' istante, il sistema operativo assegna un numero di porta TCP alla sua estremità della connessione. I due moduli di software del TCP comunicano per stabilire e verificare una connessione. Una volta che una connessione è stata creata, i programmi applicativi possono comunicare e scambiarsi i dati; i moduli software del TCP a ciascuna estremità si scambiano i messaggi che garantiscono l' affidabilità della consegna. I dettagli dell' attivazione delle connessioni saranno discussi in seguito, dopo aver esaminato il formato del messaggio TCP.
Segmenti, stream e numeri sequenziali
Il TCP considera la stream di dati come una sequenza di ottetti o byte che suddivide in segmenti per la trasmissione. Di solito, ciascun segmento viaggia attraverso un' internet datagramma IP. Il TCP impiega uno speciale meccanismo di finestra scorrevole per risolvere due importanti problemi: l' efficienza della trasmissione ed il controllo di flusso. Come il protocollo a finestra scorrevole, il meccanismo di finestra del TCP rende possibile l' invio di più segmenti prima dell' arrivo di un riscontro. In tal modo aumenta la produttività totale ( throughput ) , occupando la rete. La forma del TCP del protocollo a finestra scorrevole risolve anche il problema del controllo del flusso fra le due estremità, consentendo al ricevitore di rallentare le trasmissioni finchè non avrà uno spazio di buffer sufficiente ad ospitare altri dati.
Il meccanismo della finestra scorrevole nel TCP opera al livello di ottetto, non al livello di segmento o di pacchetto. Gli ottetti delle stream di dati sono numerati sequenzialmente, ed un trasmettitore gestisce tre puntatori associati ad ogni connessione. Tale terna di puntatori definisce una finestra scorrevole, come mostrato nella seguente figura.
Un esempio di finestra scorrevole nel TCP: gli ottetti fino a 2 sono stati trasmessi e riscontrati, quelli da 3 a 6 solamente trasmessi, e in attesa di riscontro, quelli da 7 a 9 non sono ancora stati trasmessi, ma lo saranno senza ritardi, gli ottetti da 10 in poi non potranno essere trasmessi finchè la finestra non si sarà spostata.
Il primo puntatore indica l' inizio della finestra di scorimento, separando gli ottetti che sono stati trasmessi e riscontrati da quelli ancora da trasmettere. Il secondo puntatore indica l' inizio della finestra scorrevole e definisce l' ottetto più alto nella sequenza che può essere trasmesso prima della ricezione di ulteriori riscontri. Il terzo puntatore segna all' interno della finestra il confine che separa gli ottetti che sono già inviati da quelli che restano da trasmettere. Il software del protocollo invia senza ritardo tutti gli ottetti contenuti nella finestra, cosicchè il confine si sposta rapidamente da sinistra verso destra.
Si è descritto il modo in cui la finestra del TCP viene fatta scorrere e si è menzionato che il ricevitore deve mantenere una finestra simile per ricomporla di nuovo. Comunque, è importante comprendere che, dal momento che le connessioni TCP sono full-duplex, due trasferimenti progrediscono simultaneamente in direzioni opposte in ciascuna connessione. I trasferimenti sono considerati del tutto indipendenti perchè, in un qualsiasi istante, i dati possono fluire lungo la connessione in una sola direzione o in entrambe. Pertanto, il software del TCP ad ogni estremità mantiene due finestre per ogni connessione ( per un totale di quattro ): una scorre lungo la stream dei dati trasmessi, mentre l' altra scorre mentre i dati vengono ricevuti.
Una differenza tra il protocollo a finestra scorrevole del TCP ed il protocollo a finestra scorrevole semplificato descritto in precedenza è che il TCP consente alla dimensione della finestra di variare nel tempo. Ogni riscontro, che specifica il numero di ottetti che sono stati ricevuti, contiene un annuncio di finestra che specifica il numero di ottetti di dati che il ricevitore è preparato ad accettare. Si può considerare l' annuncio di finestra come un' indicazione della dimensione corrente del buffer del ricevitore. In risposta ad un annuncio di finestra ridotta, il trasmettitore accresce la dimensione della sua finestra scorrevole e sospende la trasmissione di ottetti oltre il confine. Il software del TCP non dovrebbe contraddire i precedenti annunci restrigendo la finestra oltre le posizioni precedentemente accettabili nella stream di ottetti; invece, gli annunci più piccoli accompagnano i riscontri, per cui la dimensione della finestra cambia nell' istante in cui scorre in avanti.
Il vantaggio della dimensione variabile della finestra è quello di fornire un controllo di flusso oltre all' affidabilità del trasferimento. Quando il ricevitore si accorge che il suo buffer sta per riempirsi, col rischio di non poter ospitare altri pacchetti, trasmette un annuncio di riduzione della finestra. Nel caso estremo, il ricevitore annuncia una dimensione zero della finestra, allo scopo di annullare qualsiasi trasmissione. In seguito, allorchè ci sarà spazio disponibile nel buffer, il ricevitore annuncerà una dimensione della finestra diversa da zero, per ripristinare il flusso di dati.
Un meccanismo per il controllo di flusso è essenziale in un ambiente internet, in cui macchine di varia velocità e dimensioni e comunicano attraverso reti e gateway con altre caratteristiche. In realtà, ci sono due problemi indipendenti di flusso. Primo, i protocolli internet necessitano di un controllo di flusso end-to-end fra la provenienza e la destinazione finale. Per esempio, quando un minicomputer comunica con un grande mainframe, il primo deve regolare il flusso di dati in entrata, altrimenti il software del protocollo sarebbe ben presto sopraffatto. Quindi il TCP deve implementare un controllo di flusso end-to-end per garantire l' affidabilità della consegna. Secondo, i protocolli internet necessitano di un meccanismo di controllo del flusso che consenta ai sistemi intermedi ( ad esempio i gateway ) di controllare una provenienza che genera più traffico di quanto la macchina non ne possa gestire.
Quando le macchine intermedie diventano sovraccariche, si verifica la cosiddetta congestione, per risolvere la quale si impiegano dei metodi di controllo. Il TCP impiega il suo metodo della finestra scorrevole per risolvere il problema del controllo end-to-end, ma non ha alcun mezzo apposito per il controllo della congestione.
Il formato del segmento TCP
L' unità di trasferimento tra il software del TCP su due macchine è detta segmento. Le due macchine si scambiano segmenti per stabilire connessioni, per trasferire dati, per inviare riscontri, per annunciare le dimensioni delle finestre e per chiudere le connessioni. Poichè il TCP impiega il piggybacking, un riscontro che viaggi dalla macchina A alla macchina B può essere trasportato nel medesimo segmento dei dati che viagggiano dalla macchina A verso la B, anche se i riscontri si riferiscono ai dati inviati da B ad A. La seguente figura illustra il formato del segmento TCP:
Il formato del segmento TCP con un' intestazione seguita dai dati. I segmenti sono usati per stabilire le connessioni e per trasportare dati e riscontri.
ciascun segmento è suddiviso in due parti, cioè un' intestazione seguita dai dati. La prima, nota come intestazione TCP, trasporta l' identificazione e le informazioni di controllo che si aspettano. I campi PORTA DI PROVENIENZA e PORTA DI DESTINAZIONE contengono i numeri di porta del TCP che identificano i programmi applicativi alle estremità della connessione. Il campo NUMERO SEQUENZIALE identifica la posizione nella stream di byte del trasmettitore dei dati nel segmento. Il camppo NUMERO RISCONTRO identifica il numero dell' ottetto che la provenienza si aspetta di ricevere successivamente. Si noti che il numero sequenziale si riferisce alla stream che fluisce nella medesima direzione del segmento, mentre il numero di riscontro si riferisce alla stream che fluisce nella direzione opposta come segmento. Il campo HLEN contiene un intero che specifica la lunghezza del segmento misurata in multipli di 32 bit. Questo campo è necessario perchè il campo OPZIONI è la lunghezza variabile, a seconda delle opzioni che sono state incluse. Pertanto, la dimensione dell' intestazione TCP varia a seconda delle opzioni selezionate. Il campo di 6 bit chiamato RISERVATO è riservato all' uso futuro.
Alcuni segmenti trasportano soltanto un riscontro mentre altri trasportano dati. Altri segmenti trasportano richieste per stabilire o chiudere una connessione. Il software del TCP impiega il campo di 6 bit denominato BIT DI CODICE per determinare lo scopo e il contenuto del segmento. I sei bit dicono come interpretare altri campi nell' intestazione in base alla seguente tabella:
I bit nel campo CODICE nell' intestazione del TCP.
Il software del TCP annuncia la quantità di dati che è disposto ad accettare ogni volta che trasmette un segmento, specificando la sua dimensione di buffer nel campo FINESTRA. Il campo contiene un intero senza segno di 32 bit nell' ordine di byte standard della rete. Gli annunci di finestra forniscono un altro esempio di piggybacking perchè accompagnano tutti i segmenti, quelli che trasportano dati come pure quelli che trasportano soltanto un riscontro.
Non tutti i segmenti inviati attraverso una connessione avranno la medesima dimensione ( lunghezza ); tuttavia, le due estremità dovranno essere concordi sul valore massimo di tale dimensione. Il software TCP impiega il campo OPZIONI per negoziare col software all' altra estremità della connessione: una delle opzioni consente di specificare la dimensione massima del segmento ( Maximun Segment Size: MSS ) che è disposto a ricevere. Per esempio, quando un piccolo personal computer avente soltanto poche centinaia di byte di spazio di buffer si connette ad un grande supercomputer, esso può negoziare una MSS che limita i segmenti in modo da essere contenibili nel buffer stesso. E' particolarmente importante che i computer connessi a reti locali ad alta velocità scelgano una dimensione massima del segmento che riempia i pacchetti, altrimenti non sfrutterebbero al meglio la larghezza di banda disponibile. Pertanto, se i due punti terminali si trovano nella medesima rete fisica, di solito il TCP calcola una dimensione massima del segmento in modo che i datagrammi IP risultanti abbiano una lunghezza coincidente con la MTU della rete. Se i punti terminali non appartengono alla medesinma rete fisica, la specifica attuale suggerisce di usare il valore 256 per la dimensione massima del segmento ( tale valore si ottiene dalla differenza tra la dimensione di default di un datagramma IP, 576, e la dimensione standard delle intestazioni IP e TCP ).
In un ambiente internet generico, la scelta del valore ottimale della MSS può essere difficile, perchè le prestazioni possono degradarsi per scelte di valori estremamente piccoli o estremamente grandi. Da un lato, quando la dimensione del segmento è piccola, l' utilizzazione della rete rimane bassa. Per comprenderne il motivo si ricordi che i segmenti TCP viaggiano incapsulati in datagrammi IP che, a loro volta, sono incapsulati in frame della rete fisica. Quindi, ciascun segmento ha almeno 40 ottetti di intestazioni TCP o IP oltre ai dati. Pertanto i datagrammi che trasportano un solo ottetto di dati utilizzano al più 1/41 della lunghezza di banda della rete sottostante per i dati degli utenti; in pratica, le separazioni minime fra i pacchetti e i bit di framing dell' hardware di rete rendono ancora più piccolo tale rapporto.
Dall' altro lato, anche dimensioni estremamente grandi dei segmenti possono causare una riduzione delle prestazioni. I grandi segmenti si traducono in grandi datagrammi IP. Quando questi datagrammi viaggiano attraverso una rete avente una piccola MTU, l' IP deve frammentarli. A differenza dei datagrammi, i frammenti non sono messaggi indipendenti; tutti i frammenti devono arrivare altrimenti l' intero datagramma deve essere ritrasmesso. Poichè la probabilità di perdere un certo frammento non è zero, scegliere una dimensione del segmento al di sopra della soglia di frammentazione riduce la probabilità di arrivo del datagramma, e di conseguenza si riduce anche la probabilità di riuscita.
In teoria, la dimensione ottimale del segmento: S, si ha quando i datagrammi IP che trasportano i segmenti sono i più grandi possibili senza richiedere la frammentazione in alcun punto lungo il percorso dalla provenienza alla destinazione. In pratica la determinazione di S è difficile per vari motivi. Primo, il TCP non dispone di un meccanismo per farlo. Secondo, poichè i gateway in un' internet possono modificare dinamicamente i percorsi, il percorso seguito dai datagrammi tra una coppia di computer comunicanti può cambiare, e così pure la lunghezza a cui devono essere frammentati i datagrammi. Terzo, la dimensione ottimale dipende dalle intestazioni di protocolli di livello inferiore ( ad esempio, la dimensione del segmento deve essere ridotta per gestire le opzioni dell' IP ). Diversi progetti di ricerca stanno esplorando i modi di determinare la dimensione ottimale del segmento, ma naturalmente non esiste nessuno standard.
Dati fuori banda
Anche se il TCP è un protocollo orientato alla stream, talvolta è importante che il programma ad un' estremità di una connessione trasmetta dei dati fuori banda, senza aspettare che il programma all' altra estremità della connessione consumi ottetti già contenuti nella stream. Per esempio, quando il TCP è usato per una sessione di login remoto, l' utente può decidere di trasmettere una sequenza da tastiera che interrompe o fa abortire il programma all' altra estremità. Tali segnali sono spesso necessari quando un programma nella macchina remota non funziona correttamente. I segnali devono essere trasmessi senza aspettare che il programma legga gli ottetti già presenti nella stream TCP ( o non si potrebbero far abortire i programmi che smettono di leggere l' input ).
Per poter gestire la segnalazione fuori banda, il TCP consente al trasmettitore di specificare i dati come urgenti, nel senso che il programma ricevente dovrebbe essere avvisato del loro arrivo il più rapidamente possibile, indipendentemente dalla loro posizione nella stream. Il protocollo specifica che quando si trovano dei dati urgenti, il TCP ricevente dovrebbe avvisare qualsiasi programma applicativo associato con la connessione, affinchè tali programmi passino nella modalità di urgenza. Quando tutti i dati urgenti sono terminati, il TCP comunica al programma applicativo di tornare nella modalità normale.
I dettagli precisi del modo in cui il TCP informa il programma applicativo sui dati urgenti dipendono ovviamente dal sistema operativo del computer. Il meccanismo usato per contrassegnare i dati urgenti quando vengono trasmessi in un segmento consiste nel bit di codice URG e del puntatore PUNTATORE URGENTE. Quando il bit URG è attivato, il puntatore suddetto specifica la posizione della fine dei dati urgenti nella finestra.
Calcolo del checksum nel TCP
Il campo CHECKSUM nell' intestazione del TCP contiene un checksum intero di 16 bit che serve a verificare l' integrità dei dati come pure l' intestazione del TCP. Per calcolarlo, il software del TCP nella macchina trasmittente segue una procedura simile a quella per l' UDP. Esso aggiunge una pseudointestazione davanti al segmento, inserendo alla fine di questo tanti zeri quanti ne servono per renderlo un multiplo di sedici e calcola il checksum di 16 bit sull' intera sequenza così ottenuta. Il TCP non conta gli zeri di riempimento nella lunghezza del segmento, nè li trasmette. Inoltre presuppone che il campo CHECKSUM stesso valga zero ai fini del calcolo. Come negli altri casi, il TCP impiega l' aritmetica in complemento ad uno. All' estremità ricevente, il software analogo esegue il medesimo calcolo per verificare che i segmenti arrivino intatti.
Lo scopo principale della pseudointestazione è lo stesso che nell' UDP: essa consente al ricevitore di verificare che il segmento abbia raggiunto la sua corretta destinazione, che comprende sia l' indirizzo IP dell' host che un numero di porta del protocollo. Entrambi gli indirizzi IP di provenienza e di destinazione sono significativi per il TCP, che li deve utilizzare per identificare la connessione a cui il segmento appartiene. Pertanto ogni volta che arriva un datagramma che trasporta un segmento TCP, l' IP deve passare al TCP gli indirizzi di provenienza e di destinazione dal datagramma oltre al segmento stesso. La seguente figura illustra il formato della pseudointestazione analizzata nel calcolo del checksum.
Il TCP trasmittente assegna al campo PROTOCOLLO il valore che il sottostante sistema di consegna utilizzerà nel suo campo di tipo del protocollo. Per i datagrammi IP che trasportano il TCP, tale valore è 6. Il campo LUNGHEZZA TCP specifica la lunghezza totale del segmento TCP, includendo l' intestazione.
All' estremità ricevente, l' informazione utilizzata nella pseudointestazione viene estratta dal datagramma IP che ha trasportato il segmento ed inclusa nel checksum per verificare che il segmento sia arrivato intatto alla destinazione.
Formato della pseudointestazione impiegata nel calcolo del checksum del TCP. All' estremità ricevente, l' informazione viene estratta dal datagramma IP che ha trasportato il segmento.
Riscontri e Ritrasmissioni
Poichè il TCP invia in segmenti di lunghezza variabile e poichè i segmenti ritrasmessi possono includere più dati dell' originale, i riscontri non possono riferirsi facilmente a datagrammi o a segmenti, ma invece fanno riferimento ad una posizione nella stream usando i suoi numeri sequenziali. Il ricevitore raccoglie gli ottetti di dati dai segmenti in arrivo e ricostruisce una copia esatta della stream inviata. Poichè i segmenti viaggiano in datagrammi IP, essi possono essere persi o consegnati disordinatamente: il ricevitore impiega i numeri di sequenza per riordinare i segmenti. In qualsiasi istante, il ricevitore avrà ricostruito zero o più ottetti in modo contiguo dall' inizio della stream, ma potrebbe avere altri pezzi da datagrammi che sono arrivati fuori ordine. Il ricevitore riscontra sempre il più lungo prefisso contiguo della stream che è stato ricevuto correttamente.
Ogni riscontro specifica un valore sequenziale che è uguale alla massima posizione di ottetto nel prefisso contiguo ricevuto, più 1. Cioè il trasmettitore riceve un feedback dal ricevitore mentre progredisce attraverso la stream. Il metodo dei riscontri nel TCP è detto cumulativo perchè specifica la porzione della stream che è stata accumulata. I pricipali vantaggi dei riscontri è che sono facili da generare, non sono ambigui e che la loro perdita non obbliga necessariamente la ritrasmissione. Uno dei maggiori svantaggi è che il trasmettitore non riceve informazioni su tutte le trasmissioni riuscite, ma soltanto su una singola posizione nella stream che è stata ricevuta.
Per comprendere il motivo per cui la mancanza di informazioni su tutte le trasmissioni riuscite rende meno efficiente il protocollo, si consideri una finestra che si estende su 5000 ottetti a partire dalla posizione 101 nella stream, e si supponga che il trasmettitore abbia inviato tutti i dati ( presenti nella finestra ) trasmettendo cinque segmenti. Si supponga inoltre che il primo segmento venga perso, ma che tutti gli altri arrivino intatti. Il ricevitore continua ad inviare riscontri, ma essi specificano tutti l' ottetto 101, cioè il massimo ottetto contiguo che esso si aspetta di ricevere. Non c' è alcun modo in cui il ricevitore possa dire al trasmettitore che è arrivata la maggior parte dei dati per la finestra corrente.
Quando si verifica una condizione di tempo scaduto all' estremità del trasmettitore, questo deve scegliere fra due metodi potenzialmente inefficienti: ritrasmettere tutti e cinque i segmenti o solo quello mancante. Naturalmente, quando arriva il segmento ritrasmesso, il ricevitore avrà ricevuto correttamente tutti i dati dalla finestra, per cui invierà un riscontro specificante che il prossimo ottetto che si aspetta di ricevere ( è il 5101 ). Tuttavia, tale riscontro potrebbe non raggiungere il trasmettitore abbastanza rapidamente da impedire la ritrasmissione non necessaria di altri segmenti dalla finestra. Se il trasmettitore segue la strategia di implementazione accettata e ritrasmette soltanto il primo segmento non riscontrato, esso dovrà aspettare il riscontro prima di poter decidere quali e quanti dati inviare. Così facendo, si torna ad un semplice protocollo a riscontro positivo e si possono perdere i vantaggi derivanti da una finestra di grandi dimensioni.
Timeout e ritrasmissione
Una delle idee più importanti e complesse nel TCP è implicata nel modo in cui il protocollo gestisce le condizioni di timeout ( tempo scaduto ) e la ritrasmissione. Al pari di altri protocolli affidabili, il TCP si aspetta che la destinazione invii dei riscontri ogni volta che riceve correttamente nuovi ottetti dalla stream di dati. Dopo che un segmento viene trasmesso, il TCP avvia un timer ed attende un riscontro. Se il timer scade prima che i dati del segmento siano stati riscontrati, il TCP presuppone che il segmento sia stato perso o alterato e quindi lo ritrasmette.
Per comprendere il motivo per cui l' algoritmo di ritrasmissione del TCP differisce dall' algoritmo impiegato in molti protocolli di rete, bisogna ricordare che il TCP è stato progettato per essere utilizzato in un ambiente internet, dove un segmento che viaggia tra una coppia di macchine può attraversare una singola rete a basso ritardo ( ad esempio, una LAN ad alta velocità ) o più reti intermedie attraverso vari gateway. Pertanto è impossibile sapere a priori quanto tempo impiegheranno i riscontri per tornare alla provenienza. Inoltre il ritardo in ciascun gateway dipende dal traffico, per cui il tempo totale perchè un segmento viaggi fino alla destinazione ed un riscontro sia portato alla provenienza varia notevolmente da un istante all' altro. Per cui il software del TCP deve gestire sia le grandi differenze nei tempi richiesti per raggiungere una destinazione al variare del carico di traffico.
Il TCP gestisce tali ritardi mediante un algoritmo di ritrasmissione adattabile. In sostanza, il TCP sorveglia le prestazioni di ogni connessione e deduce i valori ragionevoli per i timeout. Al variare delle prestazioni di una connessione, il TCP rivede il suo valore di timeout ( cioè lo adatta al cambiamento avvenuto ). Per raccogliere i dati necessari per un algoritmo adattabile, il TCP registra l' istante in cui viene inviato ciascun segmento e l' istante in cui arriva un riscontro per i dati di quel segmento. Dai due istanti, il TCP calcola il tempo trascorso, noto come tempo di andata e ritorno campione o come campione di andata e ritorno. Ogni volta che ottiene un nuovo campione di andata e ritorno, il TCP regola la sua nozione di tempo medio di andata e ritorno per la connessione. Di solito, il software del TCP memorizza le stima del tempo di andata e ritorno ( Round Trip Time: RTT ) come media pesata e utilizza i nuovi campioni per variarla lentamente. Per esempio, quando si calcola una nuova media pesata, una delle prime tecniche di media utilizza un fattore di peso costante, A ( con valori maggiore o uguali a zero e minori di uno ), per pesare la vecchia media rispetto all' ultimo campione di andata e ritorno:
RTT= ( A * Vecchio_RTT ) + ( 1- A ) * Nuovo_Campione_Andata/Ritorno
La scelta di un valore di A prossimo a 1 rende la media pesata immune alle variazioni nel breve periodo ( ad esempio, un solo segmento che sperimenti un lungo ritardo ). Scegliendo un valore di A prossimo a 0, la media pesata risponderà molto prontamente alle variazioni del ritardo.
Quando invia un pacchetto, il TCP calcola il valore di timeout come funzione della stima corrente di andata e ritorno. Invece le vecchie implementazioni usavano un fattore di peso costante B ( maggiore di 1 ) e rendevano il timeout maggiore della stima corrente del tempo di andata e ritorno.
Timeout = B * RTT
La scelta di un valore di B può essere difficile. Da un lato, per rilevare rapidamente la perdita dei pacchetti, il valore del timeout dovrebbe essere prossimo al tempo di andata e ritorno ( cioè B dovrebbe essere vicino a 1 ). La rilevazione della perdita migliora rapidamente la produttività, perchè il TCP non aspetterà un tempo più lungo del necessario prima della ritrasmisssione. D' altro canto se B = 1, il TCP pecca di eccessivo zelo: qualsiasi piccolo ritardo causerà una trasmissione non necessaria con un conseguente spreco della larghezza di banda. La specifica originale consigliava di porre B = 2; gli studi più recenti hanno però prodotto tecniche migliori per la regolazione del timeout.
In teoria la misurazione di un campione di andata e di ritorno è banale: consiste nel sottrarre l' istante in cui il segmento viene trasmesso dall' istante in cui arriva il riscontro. Tuttavia, sorgono delle complicazioni perchè il TCP impiega un metodo di riscontro cumulativo, in cui un riscontro si riferisce ai dati ricevuti, e non ad uno specifico datagramma che li ha trasportati. Si consideri una ritrasnissione. Il TCP forma un segmento, lo pone in un datagramma e lo invia; il timer scade; il TCP trasmette di nuovo il segmento in un secondo datagramma. Poichè entrambi i datagrammi trasportano esattamente gli stessi dati, il trasmettitore non ha alcun modo di sapere se un riscontro corrisponda al datagramma originale o a quello ritrasmesso. Questo fenomeno è stato definito come ambiguità del riscontro ed i riscontri del TCP sono detti ambigui.
Il problema stà nel fatto che non funziona nè l' associazione del riscontro con la prima trasmissione, nè la ritrasmissione. Infatti il primo caso può far crescere senza limite il tempo stimato di andata e ritorno nel caso in cui un' internet perda i dati ( se arriva un riscontro dopo una o più ritrasmissioni, il TCP misurerà il campione di andata e ritorno dalla trasmissione originale e calcolerà un nuovo RTT usando il campione eccessivamente lungo ). Mentre nel secondo caso se il ritardo end-to-end cresce all' improvviso il TCP usa la vecchia stima del tempo di andata e ritorno per calcolare un tempo limite che ora è troppo piccolo ( l' aumento del ritardo significa che il timer scadrà prima che arrivi il riscontro, per cui il TCP ritrasmetterà il segmento ).
Per risolere tali problemi è sufficiente che il TCP non aggiorni la stima del tempo di andata e ritorno. Questa idea è nota come algoritmo di Karn ed evita del tutto il problema dei riscontri ambigui, regolando il tempo stimato per riscontri, appunto, non ambigui ( i riscontri che arrivano per i segmenti che sono stati trasmessi una sola volta).
Naturalmente, un' implementazione semplicistica dell' algoritmo di Karn, una che si limiti ad ignorare i tempi dai segmenti ritrasmessi, può condurre anch' essa ad un fallimento. Si consideri ciò che accade quando il TCP trasmette un segmento dopo una brusca crescita del ritardo. Il TCP calcola un timeout utilizzando la stima di andata e ritorno esistente. Il timeout sarà troppo piccolo per il nuovo ritardo e causerà una ritrasmissione. Se il TCP ignora i riscontri dai segmenti ritrasmessi, esso non aggiornerà mai la stima ed il ciclo continua.
Per poter far fronte a tali fallimenti, l' algoritmo di Karn richiede al trasmettitore di combinare i timeout di ritrasmissione con una strategia di backoff del timer. Tale tecnica calcola un timeout iniziale impiegando una formula come quella mostrata precedentemente. Tuttavia, se il timer scade a causa di una ritrasmissione, il TCP aumenta il timeout. In effetti ogni volta che deve ritrasmettere un segmento, il TCP lo incrementa per impedire che i tempi limite diventino ridicolmente lunghi, ( nella maggior parte delle implementazioni la crescita viene limitata da un confine superiore che è maggiore del ritardo che si manifesta lungo qualsiasi cammino nell' internet ).
Le implementazioni impiegano varie tecniche per calcolare il backoff; prevalentemente, si sceglie un fattore moltiplicativo e si pone il nuovo valore a:
nuovo_timeout = Y * timeout
Il valore tipico di Y è due ( se è minore causa instabilità ).
Altre implementazioni utilizzano una tabella di fattori moltiplicativi, consentendo un backoff arbitrario ad ogni passo.
In generale, quando un' internet non funziona bene, l' algoritmo di Karn separa il calcolo del valore di timeout dalla stima corrente del tempo di andata e ritorno. Esso utillizza la stima suddetta per calcolare un valore iniziale di timeout, ma poi riporta indietro ( " back off " ) il timeout ad ogni ritrasmissione finchè non riesce a trasferire un segmento. Quando invia i segmenti successivi, mantiene il valore di timeout prodotto dal backoff. Infine, quando arriva un riscontro che corrisponde ad un segmento per cui non è necessaria la ritrasmissione, il TCP ricalcola la stima del tempo di andata e ritorno ed azzera corrispondentemente il timeout. L' esperienza ha dimostrato che l' algoritmo di Karn funziona bene anche in reti con elevate perdite di pacchetti.
La recente ricerca nella stima del tempo di andata e ritorno ha mostrato che i calcoli descritti precedendemente non sono adeguati ad una vasta gamma di variazioni di ritardo. La teoria delle code suggerisce che la variazione del tempo di andata e ritorno, K, varia proporzionalmente a 1 / ( 1 - L ) dove L è il carico corrente sulle rete ( L assume valori maggiori o uguali a zero e minori di uno ).
Se un' internet opera al 50% della sua capacita, ci si aspetta che il ritardo di andata e ritorno vari di un fattore + oppure - 2K, o 4. Quando il carico raggiunge l' 80% , ci si aspetta una variazione pari a 16. Lo standard TCP originale specifica la tecnica per stimare il tempo di andata e ritorno descritto in precedenza.
Utilizzando questa tecnica e limitando B al valore proposto di 2, ne consegue che la stima del tempo di andata e ritorno puo adattarsi a carichi del 30% al massimo.
La specifica del 1989 per il TCP richiede che le implementazioni stimino sia il tempo di andata e ritorno medio che la varianza, e che si utilizzi la varianza stimata invece della costante B. Come risultato, le nuove implementazioni del TCP possono adattarsi ad una vasta gamma di variazioni di ritardo e forniscono una produttività sostanzialmente più alta. Per fortuna, le approssimazioni richiedono pochi calcoli; si possono ricavare programmi estremamente efficienti dalle seguenti semplici equazioni:
DIFF = CAMPIONE - Vecchio_RTT
RTT = Vecchio_RTT - H * DIFF
SCARTO = Vecchio_SCART0 + H * ( | DIFF | - Vecchio_SCARTO)
dove SCARTO è la stima dello scarto quadratico medio ( radice quadrata della varianza ) ed H è una frazione compresa fra 0 e 1 che controlla la prontezza con cui il nuovo campione influisce sulla media pesata. Per l' efficienza del calco1o, il TCP sceglie un valore di H pari a 1/2, " normalizza il calcolo col fattore 2 " ed impiega l' aritmetica intera. I risultati delle ricerche suggeriscono di usare il valore n = 3.
Risposta alla congestione
Si puo avere l' impressione che il software del TCP possa essere progettato considerando l' interazione fra i due punti terminali di una connessione ed i ritardi di comunicazione fra tali punti. In pratica, tuttavia, il TCP deve anche reagire alla congestione nell' internet. La congestione è una condizione di grave ritardo causato da un sovraccarico di datagrammi in uno o più punti di commutazione (come i gatevay). Quando si manifesta una congestione, i ritardi aumentano ed il gateway comincia ad accodare i datagrammi finchè non li potrà instradare alle rispettive destinazioni. Si ricordi che ogni gateway ha una capacità di memoria finita e che i datagrammi competono per tale memoria ( cioè, in un' internet basata sui datagrammi. non c' e una preallocazione delle risorse a singole connessioni TCP). Nel caso peggiore, il numero totale di datagrammi che arrivano nel gateway congestionato cresce finchè non raggiunge la sua capacità massima ed inizia a perdere i datagrammi.
Di solito i punti terminali non conoscono i dettagli dei punti in cui è avvenuta la congestione, nè il motivo che l' ha causata. Per essi, la congestione significa semplicemente un aumento del ritardo. Purtroppo. la maggior parte dei protocolli di trasporto impiega la tecnica di timeout e di ritrasmissione, per cui i punti termina!i rispondono all' aumento del ritardo ritrasmettendo i datagrammi. Le ritrasmissioni aggravano la congestione, invece di alleviarla: se non è controllato, l' aumento del traffico farà aumentare il ritardo, e ciò farà aumentare ancor più il traffico, e così via, finchè la rete non sarà divenuta inutilizzabile. Questa condizione è nota come collasso da congestione.
Per evitare il collasso da congestione, il TCP deve ridurre le velocità di trasmissione quando si verifica una congestione. I gateway sorvegliano le lunghezze delle code ed utilizzano tecniche come l' estinzione della sorgente ICMP per informare gli host dell' avvenuta congestione, ma i protocolli di trasporto come il TCP possono contribuire ad evitare la congestione riducendo automaticamente la velocità di trasmissione ogni volta che si hanno dei ritardi. Naturalmente, gli algoritmi per evitare la congestione devono essere progettati attentamente perchè, anche in condizioni operative normali, un' internet manifesterà una grande variazione nei ritardi di andata e ritorno.
Per evitare la congestione, l' attuale standard TCP consiglia l' impiego di due tecniche, la partenza lenta e la riduzione moltiplicativa, che sono correlate e facilmente applicabili. Si è detto che, per ogni connessione, il TCP deve ricordare la dimensione della finestra ricevuta ( cioè, la dimensione del buffer annunciata nei riscontri ). Per controllare la congestione, il TCP gestisce un secondo limite, chiamato limite della finestra di congestione, o semplicemente finestra di congestione.
In un istante qualsiasi, il TCP si comporta come se la dimensione della finestra fosse:
Finestra_ammessa = min ( annuncio_ricevitore, finestra congestione )
Nello stato stazionario di una connessione non congestionata, la dimensione della finestra di congetione è uguale a quella delIa finestra del ricevitore. La riduzione della finestra di congestione riduce il traffico che il TCP inietterà neIla connessione. Per stimare la dimensione della finestra di congestione, il TCP presuppone che la maggior parte della perdita di datagrammi sia dovuta alla congestione e adotta la seguente strategia: "riduzione moltiplicativa per evitare la congestione". Al verificarsi della perdita di un segmento, si dimezzi la finestra di congestione ( fino ad un minimo di almeno un segmento ). Per quei segmenti che restano nella finestra ammessa, si esegue il backoff esponenziale del timer di ritrasmissione.
Poichè il TCP riduce la finestra di congestione della metà per ogni perdita, esso riduce esponenzialmente la finestra se la perdita continua. In altre parole. se la congestione e probabile, il TCP riduce esponenzialmente sia il volume di traffico che la velocità di ritrasmissione. Se la perdita continua. il TCP alla fine limiterà la trasmissione ad un singolo datagramma e continuerà a raddoppiare i valori di timeout prima di ritrasmettere. L' idea è quella di fornire una rapida e significativa riduzione del traffico per offrire ai gateway un tempo sufficiente a smaltire i datagrarnmi che si trovano già nelle loro code.
In che modo il TCP ripristina le condizioni normali al termine della congestione? Si potrebbe sospettare che il TCP debba invertire la riduzione moltiplicativa, raddoppiando la finestra di congestione quando il traffico comincia a scorrere di nuovo. Tuttavia, così facendo, si avrebbe un sistema instabile che oscillerebbe selvaggiamente tra le condizioni di assenza di traffico e di congestione. Invece, il TCP impiega una tecnica chiamata partenza lenta per ripristinare la trasmissione.
La partenza lenta evita di " inondare " l' internet con altro traffico subito dopo che la congestione è scomparsa o quando vengono avviate delle nuove connessioni.
ll termine partenza lenta può essere fuorviante perchè, in condizioni ideali, la partenza non è molto lenta. ll TCP inizializza ad 1 la finestra di congestione, invia un segmento iniziale e aspetta. Quando arriva il riscontro, il TCP aumenta a 2 la finestra. trasmette due segmenti e aspetta. Quando arrivano i due riscontri. ciascuno di essi fa aumentare di l la finestra di congestione, per cui il TCP può trasmettere 4 segmenti. I relativi riscontri faranno aumentare la finestra di congestione a 8. Entro quattro tempi di andata e ritorno, il TCP puo inviare i segmenti, spesso sufficienti a raggiungere il limite della finestra del ricevitore. Anche per finestre enstremamente grandi. sono richiesti soltanto log2N viaggi di andata e ritorno prima che il TCP possa trasmettere N segmenti.
Per evitare di far crescere troppo rapidamente le dimensione della finestra e di provocare un' ulteriore congestione, il TCP aggiunge un' altra restrizione. Una volta che la finestra di congestionee ha raggiunto la metà della sua dimensione originale, il TCP entra in una fase di anticongestione e rallenta la rapidità di incremento. Durante questa fase, la dimensione della finestra aumenta di 1 solo se tutti i segmenti nella finestra sono stati riscontrati. Nell' insieme, l' aumento a partenza lenta, la riduzione moltipilcativa, l' anticongestione, la misura della variazione ed il backoff esponenziale del timer migliorano nettamente le prestazioni del TCP senza appesantire significativamente di calcoli il software del protocollo. Le versioni del TCP che impiegano queste tecniche hanno migliorato le prestazioni delle versioni precedenti di fattori compresi fra 2 e 10.
Attivazione, chiusura e reset di una connessione TCP
Per stabilire una connessione, il TCP utilizza un handshake a tre vie. Nel caso più semplice, l' handshake procede come mostrato nella seguente figura:
Sequenza dei messaggi in un hanshake a tre vie. I segmenti SYN trasportano le informazioni sui numeri sequenziali iniziali.
Il primo segmento di un handshake può essere identificato dal fatto di avere il bit SYN ( sincronizzazione ) attivato nel campo del codice. Il secondo messaggio ha attivati sia il bit SYN che il bit ACK ( riscontro ), indicando che esso riscontra il primo segmento SYN e che inoltre prosegue l'handshake. Il messaggio finale di handshake è soltanto un riscontro e serve semplicemente ad informare la destinazione che entrambe le estremità concordano sul fatto che una connessione è stata stabilita. Di solito, il software del TCP in una macchina aspetta passivamente per l' handshake, ed il software del TCP in un' altra macchina lo avvia. Comunque, l' handshake è progettato accuratamente per funzionare anche se le macchine tentano di avviare simultaneamente una connessione. Quindi, una connessione può essere stabilita da una delle due estremità o da entrambe simultaneamente. Una volta che una connessione è stata stabilita, i dati possono fluire con la medesima efficienza in entrambe le direzioni; non ci sono "master" nè "slave". L' handshake a tre vie è necessario e sufficiente a correggere la sincronizzazione fra le due estremità della connessione. Per comprenderne il motivo, si ricordi che il TCP è costruito su un servizio non affidabile di consegna dei pacchetti, per cui i messaggi possono essere persi, ritardati, duplicati o consegnati fuori ordine. Pertanto. il protocollo deve usare un meccanismo di timeout e ritrasmettere i pacchetti persi. Sorgono dei problemi se le richieste ritrasmesse e originali arrivano mentre la connessione viene stabilita, utilizzata e terminata. Questi problemi sono risolti dall' handshake a tre vie ( più la regola, il TCP ignora l' ulteriori richiesta di connessione dopo che ne è stata stabilita una).
L' handshake a tre vie svolge due importanti funzioni. Esso garantisce che entrambe le estremità siano pronte per trasferire i dati ( e che sappiano di essere pronte entrambe) e consente alle due estremità di concordare sui numeri di sequenza iniziali. Ogni macchina deve scegliere a caso un numero di sequenza iniziale, che utilizzerà per identificare i byte nel!a stream che stà trasmettendo. I numeri sequenziali non possono iniziare sempre dallo stesso valore. In particolare, il TCP non può limitarsi a scegliere la sequenza 1 ogni volta che crea una connessione ( in uno degli esercizi alla fine del capitolo sono esaminati i problemi che potrebbero sorgere se lo facesse). Naturalmente, è importante che entrambe le estremità concordino sul numero iniziale, affinchè i numeri degli ottetti usati nei riscontri concordino con quelli usati nei segmenti di dati. Per comprendere come le macchine possano concordare sui numeri sequenziali per due stream dopo solo tre messaggi, si ricordi che ciascun segmento contiene sia un campo di numero sequenziale che un campo di riscontro.
Sia A la macchina che avvia un handshake: essa passa il suo numero di sequenza iniziale, X, nel campo di sequenza del primo segmento SYN nell' handshake a tre vie. La seconda macchina, B, riceve il SYN, registra il numero sequenziale, e risponde inviando il suo numero di sequenza iniziale nel campo di sequenza. Oltre ad un riscontro che specifica che B si aspetta l' ottetto X + l. Nel messaggio finale dell' handshake, A " riscontra " la ricezione da B di tutti gli ottetti attraverso Y. In tutti i casi, i riscontri seguono la convenzione di utitizzare il numero del successivo ottetto atteso.
Si è descritto il modo in cui il TCP svolge solitamente l' handshake a tre vie mediante uno scambio di segmenti che contengono una minima quantità di informazioni. A causa del progetto del protocollo, è possibile trasmettere i dati insieme coi numeri sequenziali iniziali nei segmenti di handshake. In tali casi, il software del TCP deve contenere i dati fino al completamento dell' handshake. Una volta che una connessione è stata stabilita, il software del TCP può rilasciare i dati mantenuti e fornirli rapidamente ad un programma applicativo in attesa.
Due programmi che impiegano il TCP per comunicare possono terminare gradualmente la conversazione utilizzando l' operazione di " chiusura " ( close ). Al suo interno, il TCP impiega un meccanismo modificato di handshake a tre vie per chiudere le connessioni. Si ricordi che le connessioni TCP sono full-duplex e si può immaginare che ciascuna di essa contenga due trasferimenti di stream indipendenti, che procedono in direzioni opposte. Quando un programma applicativo comunica al TCP di non avere piu dati da trasmettere, il TCP chiuderà la connessione in una direzione. Per chiudere la sua metà della connessione, il TCP trasmittente termina di inviare i dati che restano, aspetta che il ricevitore li riscontri e poi invia un segmento col bit FIN attivato. ll TCP ricevente riconosce il segmento FIN ed informa il programma applicativo alla sua estremità che non ci sono più dati disponibili ( ad esempio, utilizzando il meccanismo del sistema operativo per contrassegnare la fine del file).
Una volta che una connessione è stata chiusa in una certa direzione, il TCP si rifiuta di accettare altri dati in tale direzione. Nel frattempo, i dati possono continuare a scorrere nella direzione opposta finchè il trasmettitore non la chiude. Naturalmente, i riscontri continuano a scorrere all' indietro verso il trasmettitore anche dopo che una connessione è stata chiusa. Quando entrambe le connessioni sono state chiuse, il software del TCP in ciascun punto terminale cancella il suo record della connessione.
I dettagli della chiusura di una connessione sono ancor piu minuti di quanto non appaia dalla descrizione precedente, perchè il TCP impiega un handshake a tre vie modificato per chiudere una connessione. La seguente figura ne illustra la procedura.
La differenza tra gli handshake a tre vie utilizzati per stabilire e spezzare le connessioni si manifesta dopo che una macchina ha ricevuto il segmento FIN iniziale. Invece di generare immediatamente un secondo segmento FIN, il TCP invia un riscontro e quindi informa il programma applicativo della richiesta di terminare la connessione.
Per informare della richiesta il programma applicativo ed ottenere una risposta può essere necessario un tempo considerevole ( ad esempio, potrebbe richiedere un' interazione con operatori umani ). Il riscontro evita la ritrasmissione del segmento FIN iniziale durante l' attesa. Infine, quando il programma applicativo ordina al TCP di chiudere completamente la connessione, il TCP invia il secondo segmento FIN e l' estremita di origine risponde col terzo messaggio, un ACK.
Esempio di handshake a tre vie modificato per chiudere le connessioni. L' estremità che riceve il primi segmento FIN lo riscontra immediatamente e quindi aspetta prima di trasmettere il secondo.
Normalmente, un programma applicativo impiega l' operazione di chiusura per terminare una connessione quando ha finito di utilizzarla. Quindi, la chiusura di una connessione è considerata una parte normale dell' utilizzazione, analoga alla chiusura dei file. Talvolta si presentano delle condizioni anormali che costringono il programma applicativo o il software della rete a spezzare una connessione. Il TCP fornisce un mezzo per effettuare il reset di tali sconnessioni anormali. Per effettuare il reset di una connessione, un' estremità inizia la procedura di terminazione inviando un segmento col bit RST attivato nel campo CODICE.
L' altra estremità risponde immediatamente ad un reset facendo abortire la connessione. Il TCP informa anche il programma applicativo che è avvenuto un reset. Un reset è una terminazione istantanea, o " aborto ", che causa la cessazione immediata del trasferimento in entrambe le direzioni ed il rilascio delle risorse, come i buffer.
Macchina a stati finiti del TCP
Come per la maggior parte dei protocolli, le operazioni del TCP possono essere spiegate meglio col modello teorico della macchina a stati finiti. La seguente figura mostra la macchina a stati finiti del TCP con dei cerchi che rappresentano gli stati e degli archi orientati ( trecce ) che rappresentano le transizioni fra due stati.
L' indicazione su ciascuna transizione illustra ciò che il TCP riceve per far avvenire la transizione e ciò che invia in risposta. Per esempio. il software del TCP in ciascun punto terminale inizia nello stato CHIUS0. I programmi applicativi devono inviare un comando di apertura passiva ( per attendere una connessione da un' altra macchina ) o un comando di apertura attiva ( per avviare una connessione ). Un comando di apertura attiva obbliga ad una transizione dallo stato CHIUSO allo stato SYN INVIATO. Quando il TCP segue la transizione emette un segmento ACK.
Quando l' altra estremità restituisce un segmento che contiene un SYN più un ACK, il TCP si sposta sullo stato STABILIT0 ed inizia a trasferire i dati.
Lo stato ATTESA TEMPORIZZATA rivela il modo in cui il TCP gestisce i problemi dovuti alla non affidabilita della consegna. Il TCP possiede la nozione di tempo di vita massimo di un segmento, cioè il massimo tempo in cui un vecchio segmento può restare in vita in un' internet. Per evitare che dei segmenti di una connessione precedente interferiscano con una in corso, il TCP si sposta sullo stato di ATTESA TEMPORIZZATA dopo aver chiuso una connessione.
Esso resta in tale stato per il doppio del tempo di vita massimo del segmento prima di cancellare la sua registrazione della connessione.
Qualora arrivasse qualche segmento duplicato, durante l' intervallo di timeout, il TCP lo rifiuterebbe. Tuttavia, per gestire i casi in cui l' ultimo riscontro è stato perso, il TCP riscontra i segmenti validi e riavvia il timer.
Poichè il timer consente al TCP di distinguere le vecchie connessioni dalle nuove, esso impedisce al TCP di rispondere con un RST ( reset ) se l' altra estremità ritrasmette una richiesta FIN.
La macchina a stati finiti del TCP. Ciascun punto terminale inizia nello stato CHIUSO. Le diciture sulle transizioni indicano l' input, seguito eventualmente dall' output.
Forzatura della consegna dei dati
Si è detto che il TCP è libero di suddividere la stream di dati in segmenti per la trasmissione, indipendentemente dalla dimensione del trasferimento utilizzata dai programmi applicativi. Il principale vantaggio che deriva dal consentire al TCP di scegliere una suddivisione è l' efficienza. Il TCP può accumulare abbastanza ottetti in un buffer da rendere i segmenti ragionevolmente lunghi, riducendo l' alto appesantimento che si verifica quando i segmenti contengono solamente pochi ottetti di dati.
Anche se la bufferizzazione migliora la produttività della rete, essa può interferire con alcune applicazioni. Si consideri l' impiego di una connessione TCP per passare i caratteri da un terminale interattivo ad una macchina remota. L' utente si aspetta una risposta istantanea per ogni battuta dei tasti. Se il TCP di trasmissione bufferizza i dati, la risposta può essere ritardata, magari di centinaia di battute. Similmente, poichè il TCP di ricezione può bufferizzare i dati prima di renderli disponibili al programma applicativo alla sua estremità, costringere ii trasmettitore ad inviare i dati potrebbe non essere sufficiente a garantire la consegna. Per gestire gli utenti interattivi, il TCP dispone di un' operazione di spinta ( push ) che un programma applicativo può utilizzare per rendere obbligatoria la consegna di ottetti presenti al momento nella stream, senza dover aspettare che il buffer si riempia. L' operazione di spinta non si limita a costringere il TCP ad inviare un segmento: essa richiede anche al TCP di attivare il bit PSH nel campo di codice del segmento, cosicchè i dati saranno forniti al programma applicativo all' estremità ricevente. Pertanto, quando si trasmettono dei dati da un terminale interattivo l' applicazione impiega la funzione di spinta dopo ogni battuta di tasti. Similmente, i programmi applicativi possono costringere l' output ad essere trasmesso e visualizzato prontamente sul terminale chiamando la funzione di spinta dopo aver scritto un carattere o una riga.
Come l' UDP, il TCP combina l' associazione di porta statica e dinamica, impiegando in un insieme di assegnazioni di porte ben note per i programmi chiamati comunementi ( come per la posta elettronica ), ma lasciando la maggior parte dei numeri di porta disponibili al sistema operativo, che li assegnerà ai programmi quando ne avranno bisogno. La specifica stabilisce che soltanto i numeri di porta minori di 256 saranno utilizzati per le porte ben note; il resto è disponibile per applicazioni arbitrarie.
Va notato che, per quanto i numeri di porta TCP e UDP siano indipendenti, i progettisti hanno deciso di utilizzare i medesimi numeri di porta interi per qualsiasi servizio che sia accessibile sia dall' UDP che dal TCP. Per esempio, si può accedere ad un server di nomi di dominio sia col TCP che con l' UDP. In entrambi i protocolli, il numero di porta 53 è stato riservato ai server nel sistema di nomi di dominio.
Come si è visto, il TCP è un protocollo complesso che gestisce le comunicazioni su un' ampia varietà di tecnologie di rete alla base. Molti utenti credono che, dal momento che il TCP gestisce un compito molto piu complesso di quello svolto da altri protocolli di trasporto, il relativo codice debba essere pesante e di bassa efficienza. Sorprendentemente, non sembra che la generalità di cui si è discusso ostacoli le prestazioni del TCP. Gli esperimenti condotti alla Berkeley University hanno mostrato che il TCP che opera efficientemente sull' Internet puo fornire 8 Mbps di produttività sostenuta tra due workstation in una Ethernet a 10 Mbps. Alla Cray Research. inc.. alcuni ricercatori hanno verificato una produttività ( throughput ) del TCP superiore a 600 Mbps.