Sei sulla pagina 1di 27

3 - LIVELLO DI TRASPORTO

Un protocollo a livello di trasporto mette a disposizione una comunicazione logica tra processi applicativi di host
differenti. Per comunicazione logica intendiamo che dal punto di vista dell'applicazione, come se i terminali su cui
girano i processi fossero direttamente connessi; processi applicativi usano la comunicazione logica fornita dallo strato
di trasporto per scambiarsi messaggi, senza doversi preoccupare dei dettagli dell'infrastruttura fisica usata per
trasportare questi messaggi. I protocolli dello strato di trasporto sono implementati nei terminali ma non nei router
della rete.
Dal lato d'invio, il livello di trasporto converte i messaggi che riceve da un processo applicativo mittente in pacchetti a
livello di trasporto, noti come segmenti a livello di trasporto (trasport layer segment). Questo avviene (se necessario)
spezzano i messaggi applicativi in parti pi piccole e aggiungendo a ciascun frammento un'intestazione di trasporto. Il
livello di trasporto, quindi, passa il segmento al livello di rete presso il sistema terminale d'invio, ove viene incapsulato
all'interno di un pacchetto a livello di rete (datagramma) e inviato a destinazione. importante notare che i router
intermedi agiscono solo sui campi a livello di rete del datagramma, senza esaminare i campi del segmento incapsulato
nel datagramma. Alla ricezione, il livello di rete estrae il segmento dal datagramma e lo passa al livello superiore,
quello di trasporto. Quest'ultimo elabora il segmento ricevuto, rendendo disponibili all'applicazione destinataria i dati
del segmento.

Mentre un protocollo dello strato di trasporto fornisce una comunicazione logica tra due processi, che funzionano su
differenti host, un protocollo dello strato di rete fornisce la comunicazione logica fra gli host. Questa distinzione
sottile ma importante. All'interno di un sistema terminale, un protocollo di trasporto trasferisce i messaggi dai
processi applicativi all'estremit della rete e viceversa, ma non dice nulla su come i messaggi vengano trasferiti
all'interno della rete.
Ricordiamo che Internet, e pi in generale una rete TCP/IP, rende disponibili due distinti protocolli dello strato di
trasporto allo strato di applicazione. Uno di questi protocolli l'UDP (User Datagram Protocol), che fornisce alle
applicazioni che a esso si appoggiano un servizio inaffidabile, senza connessione. Il secondo di questi protocolli il TCP
(Transmission Control Protocol), che fornisce alle applicazioni un servizio affidabile orientato alla connessione. Il
protocollo dello strato di rete di Internet ha un nome: protocollo Internet (IP, Internet Protocol). L'lP fornisce la
comunicazione logica fra gli host. Il modello di servizio di IP un servizio best effort (letteralmente "miglior sforzo"),
significa che IP "fa dei suo meglio" per consegnare i segmenti tra i due host in comunicazione, ma non d garanzie. In
particolare, non garantisce la consegna dei segmenti, l'ordine di consegna e l'integrit dei dati nei segmenti. Per questi
motivi, si dice che IP un servizio inaffidabile. Ciascun host ha un unico indirizzo lP. La maggior responsabilit di UDP e
TCP di estendere il servizio di consegna di IP tra due terminali al servizio di consegna fra due processi in esecuzione
sui sistemi terminali. Questa passaggio da consegna host-to-host a consegna process-to-process detto multiplexing
e demultiplexing.

UDP e TCP forniscono anche un controllo dell'integrit inserendo campi di rilevamento di errori nelle loro intestazioni.
Questi due servizi minimali dello strato di trasporto, spedizioni di dati da processo a processo e verifica degli errori,
sono i soli due servizi forniti da UDP. TCP offre molti servizi addizionali alle applicazioni. Primo, e pi importante, esso
fornisce un trasferimento affidabile dei dati, usando controllo del flusso, numeri di sequenza, riscontri e timer. Il TCP
converte il servizio inaffidabile iP in un servizio affidabile. Il TCP usa anche il controllo della congestione, un servizio a
beneficio di Internet nel suo insieme. Come principio, il TCP permette di suddividere equamente la banda di un link
congestionato tra le connessioni TCP che la attraversano. Ci si ottiene regolando la velocit (tasso) a cui i lati dei TCP
che spediscono possono inviare il traffico nella rete. Il traffico UDP, d'altra parte, non regolabile.

3.1 MULTIPLEXING E DEMULTIPLEXING


Lo strato di trasporto nel terminale ricevente non consegna effettivamente i dati direttamente a un processo, ma ad
un socket intermediario. Poich a ogni dato istante ci pu essere pi di un soket nel terminale ricevente, ogni socket
ha un identificatore unico. Il formato delI'identificatore dipende dal fatto che sia un socket UDP o TCP. Consideriamo
ora come un terminale ricevente dirige un segmento entrante dello strato di trasporto verso il socket giusto. Ogni
segmento dello strato di trasporto ha un insieme di campi dedicati a questo scopo. All'estremit ricevente, lo strato di
trasporto esamina questi campi per determinare il socket ricevente e indirizzargli i segmenti. Questo lavoro di
recapitare i dati in un segmento dello strato di trasporto al corretto socket chiamato demultiplexing. ll lavoro di
ottenere i dati dall'host sorgente dai diversi socket, completare i dati con le informazioni di intestazione (che saranno
usate p tardi nel demultiplexing) per creare segmenti, e di passare i segmenti allo strato di rete detto multiplexing.
La multiplazione allo strato di trasporto richiede (1) che i socket abbiano identificatori unici e (2) che ogni segmento
abbia speciali campi che definiscano la socket al quale il segmento deve essere consegnato: questi campi speciali sono
il numero di porta d'origine e numero di porta di destinazione. Ciascun numero di porta a 16 bit e va da 0 a 65356. I
numeri di porta che vanno da 0 a 1023 sono chiamati numeri di porta ben conosciuti (well-known port numbers) e
sono riservati, il che significa che sono dedicati per l'uso con protocolli applicativi noti come HTTP (che usa il numero
di porta 80) e FTP (che usa il numero di porta 21).

Multiplazione e demultiplazione senza connessione


Un programma Java che gira su un terminale pu creare un socket UDP con la linea:
DatagramSocket mySocket = new DatagramSocket ( );
Quando viene creato un socket UDP in questo modo, lo strato di trasporto assegna automaticamente un numero di
porta al socket. In particolare, lo strato di trasporto assegna un numero di porta nel range da 1024 a 65535 che non
attualmente usato per alcuna delle altre porte UDP nel terminale. In alternativa, un programma Java potrebbe creare
un socket con la linea:
DatagramSocket mySocket = new DatagramSocket (19157);
Se il programmatore che sta scrivendo il codice sta realizzando il lato server di un protocollo ben noto (well known
protocol) allora il programmatore deve assegnare il corrispondente numero ben noto di porta (well known port
number). Tipicamente, il lato client dell'applicazione fa assegnare automaticamente (e trasparentemente) il numero di
porta allo strato di trasporto mentre il lato server dell'applicazione assegna un numero di porta specifico.
Supponiamo che un processo con il socket 19157 nel terminale A voglia mandare un blocco di dati di applicazione a un
processo nel terminale B con socket UDP 46428. Lo strato di trasporto nel terminale A crea un segmento dello strato
di trasporto che comprende i dati di applicazione, il numero di porta sorgente (19157) il numero di porta di
destinazione (46428) e altri due valori. Lo strato di trasporto passa quindi il segmento risultante allo strato di rete. Lo
strato di rete incapsula il segmento in un datagram IP e fa un tentativo best-effort di consegnare il segmento al
terminale ricevente. Se il segmento arriva al terminale ricevente B, quest'ultimo esamina il numero di porta di
destinazione nel segmento (46428) e consegna il segmento al suo socket identificato dalla porta 46428. da notare
che sul terminale B potrebbero essere attivi molteplici processi, ciascuno con il suo socket UDP e il numero di porta
associato. Man mano che i segmenti UDP arrivano dalla rete, il terminale B dirige (demultipla) ogni segmento verso il
socket appropriato esaminando il numero di porta di destinazione del segmento. importante notare che un socket
UDP univocamente determinato da una coppia formata da un indirizzo IP di destinazione e un numero di porta di
destinazione. Il numero di porta sorgente serve come parte di un indirizzo di ritorno.

Multiplazione e demultiplazione orientato alla connessione


Una sottile differenza tra una socket TCP una socket UDP risiede nel fatto che la prima identificata da quattro
parametri: indirizzo IP di origine, numero di porta di origine, indirizzo IP di destinazione e il numero di porta di
destinazione.
Pertanto, quando un segmento TCP giunge dalla rete in un host, quest'ultimo utilizza i quattro valori per dirigere (ossia
a demultiplexare) il segmento verso la socket appropriata. In particolare, e al contrario di UDP, due segmenti TCP in
arrivo, aventi indirizzi IP di origine con numeri di porta di origine diversi saranno dirette a due socket differenti, con
l'eccezione dei segmenti TCP che trasportano la richiesta originaria per stabilire la connessione.

L'applicazione server TCP presenta una socket di benvenuto che si pone in attesa di richieste di connessione
da parte dei client TCP sul numero di porta 6789.
Il cliente TCP genera un segmento per stabilire la connessione tramite la linea
Socket clientSocket = new Socket ("ServerHostName", 6789 );
una richiesta di connessione non nient'altro che un segmento TCP con numero di porta di destinazione
6789 e uno speciale bit posto a 1 nel intestazione TCP. Il segmento e include anche un numero di porta di
origine scelto dal client. La riga precedente crea inoltre una socket TCP per il processo client, attraverso la
quale i dati possono fruire in ingresso e in uscita dal processo client.
Quando l'host server riceve il segmento con la richiesta di connessione con porta di destinazione 6789, crea
una nuova connessione:
Socket connectionSocket = welcomeSocket.accept( );

3.2 TRASPORTO SENZA CONNESSIONE: UDP


UDP, a parte la funzione di multiplexing/demultiplexing e una forma leggera di controllo dell'errore non aggiunge nulla
a IP. Uno sviluppatore potrebbe scegliere di costruire un'applicazione su UDP per i seguenti motivi:
controllo a livello di applicazione pi sottile
nessuna connessione stabilita
nessuno strato di connessione
intestazione di pacchetto pi corta

L'intestazione UDP presenta solo quattro campi, di due byte per ciascuno. L'host ricevente utilizza la checksum per
verificare se sono avvenuti errori nel segmento. Il campo lunghezza specifica la lunghezza, in byte, del segmento UDP,
compresa l'intestazione.

La checksum UDP server per il rilevamento degli errori. Sul lato d'invio, UDP effettua il completamento bit a bit della
somma di tutte le parole da 16 bit nel segmento, e l'eventuale riporto finale viene sommato il primo bit.
Supponiamo pertanto di avere le seguenti tre parole da 16 bit:
0110011001100110
0101010101010101
0000111100001111
La somma delle prime due di queste parole di 16 bit
0110011001100110 +
0101010101010101 =
1011101110111011
Aggiungendo la terza parola la somma d
1011101110111011 +
0000111100001111 =
1100101011001010
Il complemento bit a bit si ottiene convertendo i bit 0in bit 1 e viceversa. Di conseguenza la checksum sar
0011010100110101. Sn ricezione si sommano le tre parole iniziali e la checksum. Se non ci sono errori del pacchetto
allora l'addizione dar 1111111111111111, altrimenti sappiamo che stato introdotto un errore del pacchetto.
UDP mette a disposizione una checksum perch non c' garanzia che tutti i collegamenti tra origine e destinazione
controllino gli errori. Inoltre, anche se i segmenti fossero trasferiti correttamente lungo collegamento, si potrebbe
verificare un errore mentre il segmento si trova nella memoria di un router. Questo un esempio del principio puntopunto in base al quale, dato che determinate funzionalit devono essere implementate su base punto-punto, le
funzioni posizionate livelli inferiori possono essere ridondanti o di scarso valore rispetto al costo di fornirle al livello
superiore.

3.3 PRINCIPI DI TRASFERIMENTO DATI AFFIDABILE


Il problema del trasferimento dati affidabile si verifica non solo a livello di trasporto ma anche a livello di collegamento
e di applicazione. L'astrazione del servizio offerta all'entit dei livelli superiori quella di un canale affidabile tramite il
quale si possono trasferire dati. Il compito dei protocolli di trasferimento dati affidabile l'implementazione di
questa astrazione. Ci reso difficile dalla possibile inaffidabilit del livello al di sotto del protocollo di trasferimento
dati. Il livello sottostante due punti terminali che comunicano in modo affidabile pu consiste di un singolo
collegamento fisico o di una rete. Per i nostri scopi comunque possiamo vedere questo livello inferiore semplicemente
come un canale inaffidabile punto-punto. Il lato d'invio del protocollo di trasferimento dati sar invocato dall'alto
tramite una chiamata a rdt_send() e trasferir i dati da consegnare al livello superiore sul lato di ricezione. In
questo caso rdt sta per le reliable data transfer e _send indica la chiamata del lato d'invio di rdt. Alla ricezione,

quando un pacchetto giunge dal lato ricevente del canale si chiamer rdt_rcv(). Rei momenti in cui il protocollo
rdt vuole consegnare dati al livello superiore lo far richiamando deliver_data().
Consideriamo solo il caso di trasferimento dati unidirezionale. Il caso bidirezionale (ossia full-duplex) non
concettualmente pi difficile ma pi noioso da spiegare. Sia il lato d'invio sia quello di ricezione di rdt inviano pacchetti
tramite una chiamata udt_send()(unreliable data trasfert).

Consideriamo il caso di un canale che commette errori sui bit e assumiamo che tutti i pacchetti trasmessi vengano
ricevuti nell'ordine d'invio. I protocolli di trasferimento dati affidabili basati su ritrasmissioni sono noti come protocolli
ARQ (automatic repeat request). I protocolli ARQ devono avere tre capacit aggiuntive:
rilevamento di errore: richiesto un meccanismo che consente al destinatario di rilevare gli errori sui bit; tali tecniche
richiedono l'invio di bit extra tra mittente e destinatario;
feedback del destinatario: dato che mittente e destinatario sono generalmente in esecuzione sui sistemi terminali
diversi, l'unico modo che ha il mittente per conoscere la visione del destinatario consiste nel feedback esplicito del
destinatario; le risposte di notifica positiva (ACK) e negativa (NAK) sono esempi di feedback;
ritrasmissione: un pacchetto ricevuto con errori sar ritrasmesso.
Il lato d'invio riceve l'istruzione dallo strato di applicazione e creer un pacchetto che contiene i dati da inviare insieme
a una checksum di pacchetto. Sul lato di ricezione all'arrivo del pacchetto senza errori, il destinatario invia un
pacchetto ACK al mittente, al contrario, se il pacchetto giunge con errori sui bit, evidenziati da una checksum
scorretta, il destinatario invier un pacchetto NAK al mittente. Il mittente quindi non invier nuovi dati finch non
certo che il destinatario abbia ricevuto correttamente il pacchetto corrente: questi protocolli sono noti come
protocolli di stop-and-wait.
Dobbiamo tenere conto la possibilit che i pacchetti ACK e NAK possano a loro volta essere alterati. L'aggiunta di bit di
checksum sufficienti a consentire al mittente non solo di trovare ma anche di correggere gli errori subiti risolverebbe il
problema immediato per un canale che pu danneggiare pacchetti ma non perderli. Potremmo anche prevedere
semplicemente che il mittente rinvii il pacchetto di dati corrente a seguito della ricezione di un pacchetto ACK o NAK
alterato ma questo approccio introduce pacchetti duplicati nel canale: la fondamentale difficolt insita nella
duplicazione di pacchetti e che il destinatario non sa se l'ultimo ACK inviato sia stato ricevuto correttamente dal
mittente, di conseguenza non pu sapere a priori se un pacchetto in arrivo contenga dati nuovi o rappresenti una
ritrasmissione. Una soluzione semplice questo problema consiste nel aggiungere un campo al pacchetto dati
obbligando il mittente a numerare i propri pacchetti dati con un numero di sequenza posto nel nuovo campo. Al
destinatario sar sufficiente controllare questo numero per sapere se il pacchetto ricevuto rappresento una
ritrasmissione. Dato che stiamo ipotizzando che il canale non perda pacchetti, i pacchetti ACK e NAK non devono

indicare il numero di sequenza del pacchetto di cui rappresentano la notifica. Il mittente sa che un pacchetto ricevuto
di tipo ACK o NAK stato generato come risposta al pacchetto dati trasmesso pi di recente.
Possiamo ottenere lo stesso effetto di un NAK se, invece di inviarne uno, spediamo piuttosto un ACK per il pi recente
pacchetto ricevuto correttamente. Un mittente che riceve due ACK per lo stesso pacchetto (ossia riceve ACK duplicati)
sa che il destinatario non ha ricevuto correttamente il pacchetto successivo a quello confermato due volte. In questo
caso il destinatario deve ora includere il numero di sequenza del pacchetto di cui invia il riscontro all'interno del
messaggio a check-up.
Consideriamo ora un canale di trasmissione che, oltre a danneggiare i bit, possa anche smarrire i pacchetti. L'utilizzo
dei checksum, numeri di sequenza, pacchetti a check-up e ritrasmissione, ci permettono di rilevare lo smarrimento ma
non di rimediare a quest'ultimo. Supponiamo che un pacchetto dati o l'ACK corrispondente vada smarrito; in entrambi
i casi, il mittente non otterr alcuna risposta da parte del destinatario. Se il mittente disposto ad attendere un tempo
sufficiente per essere certo dello smarrimento del pacchetto, pu semplicemente ritrasmettere il pacchetto di dati. Il
mittente deve attendere perlomeno il minimo ritardo di andata e ritorno tra mittente e destinatario, pi il tempo
richiesto per elaborazione di un pacchetto da parte del destinatario. In molte reti questo ritardo relativo difficile da
stimare. L'approccio adottato nella pratica di scegliere in modo assennato un valore di tempo tale per cui la perdita
di pacchetti risulta probabile anche se non garantita. Se un pacchetto sperimenta un ritardo particolarmente lungo, il
mittente potrebbe ritrasmetterlo anche se non andato smarrito, questo introduce la possibilit di pacchetti dati
duplicati sul canale tra mittente e destinatario. Il mittente non sa se un pacchetto dati sia andato perduto, se sia stato
smarrito un ACK o se il pacchetto o l'ACK abbiano semplicemente subito un notevole ritardo. In tutti questi casi,
l'azione intrapresa la stessa: ritrasmettere. Implementare un meccanismo di ritrasmissione passato sul tempo
richiede un contatore in grado di segnalare al mittente l'avvenuta scadenza di un dato lasso di tempo. Il mittente sar
quindi in grado (1) di inizializzare il contatore ogni volta che invia un pacchetto (2) di rispondere a un interrupt
generato dal timer e (3) di fermare il contatore. Poich stiamo ipotizzando di inviare un pacchetto alla volta non
appena ricevuto il feedback dal destinatario, i numeri di sequenza dei pacchetti alternano tra 0 e 1, quest'ultimo
protocollo viene quindi detto ad alternanza di bit.

Il problema delle prestazioni del protocollo appena visto risiede nel fatto che si tratta di un protocollo host open with.
Per valutare l'impatto delle prestazioni di questo comportamento, consideriamo il caso idea di due host, uno sulla
costa occidentale degli Stati Uniti e l'altro sulla costa orientale. Il ritardo di propagazione di andata e ritorno (RTT round trip time) alla velocit della luce per questi due sistemi terminali approssimativamente di 30 ms. Supponiamo
che i due sistemi siano connessi da un canale con tasso trasmissivo R di 1 Gb per secondo. Con pacchetti di
dimensione L, di 1000 byte (8000 bit), inclusi i campi di intestazione e dati, il tempo effettivamente richiesto per
trasmettere il pacchetto sul collegamento :
=

8000 /
=
= 8

109 /

l'ultimo bit entra nel canale sul lato d'invio al tempo di t=8 microsecondi. Il pacchetto quindi effettua un viaggio di 15
ms attraverso il continente, e l'ultimo bit del pacchetto giunge al destinatario all'istante t=15,008 ms. L'ACK giunge al
mittente all'istante t = RTT + L/R = 30,008 ms. Quindi, in un arco di 30,008 ms, il mittente ha trasmesso solo per 0,008
ms. Definiamo l'utilizzo del mittente come la frazione di tempo in cui il mittente stato effettivamente occupato
nell'invio di bit sul canale, l'analisi mostra che il protocollo stop-and-wait presenta un utilizzo del mittente pari a
=

/
0,008
=
= 0,00027
+ /
30,008

Il mittente stato in grado di spedire con un throughput effettivo di soli 267 Kbps nonostante fosse disponibile un
collegamento da 1 Gbps. Una soluzione operare in modalit pipelining consentendo al mittente di trasmettere tre
pacchetti senza dover aspettare i riscontri. Ovviamente una, l'intervallo di numeri di sequenza disponibili deve essere
incrementato e i lati d'invio e di ricezione dei protocolli possono dover bufferizzare pi di un pacchetto. La quantit di
numeri di sequenza necessari e i requisiti di buffering dipenderanno dal modo in cui il protocollo di trasferimento dati
risponde ai pacchetti smarriti, alterati o troppo in ritardo.
Si possono identificare due approcci di base verso la risoluzione degli errori con pipeline: Go-Back-N e ripetizione
selettiva.

GO-BACK-N
In un protocollo Go-back-N (GBN), il mittente pu trasmettere il senza dover attendere la notifica, ma non pu avere
pi di N pacchetti in attesa di notifica. Se definiamo base il numero di sequenza del pacchetto pi vecchio non ancora
riscontrato e nextseqnum il pi piccolo numero di sequenza inutilizzato (ossia il numero di sequenza del prossimo
pacchetto da inviare), allora si possono identificare quattro intervalli di numeri di sequenza. I numeri di sequenza
nell'intervallo [0, base-1] corrispondono ai pacchetti che sono gi stati trasmessi riscontrati. L'intervallo [base,
nextseqnum] corrisponde ai pacchetti che sono stati inviati ma non ancora riscontrati. I numeri di sequenza
nell'intervallo [nextseqnum, base+N-1] possono essere utilizzati per i pacchetti da inviare immediatamente, nel caso
arrivassero dati del livello superiore. Infine, i numeri di sequenza maggiore uguale base + N non possono essere
utilizzati fino a quando il mittente non riceve riscontro di un pacchetto che si trova nella linea ed ancora privo di
riscontro (nella specifico, e il pacchetto con il numero di sequenza base). N viene spesso chiamata ampiezza della
finestra e il protocollo GBN viene detto protocollo a scorrimento di finestra.
Il numero di sequenza di un pacchetto in un campo dell'intestazione, detto K il numero di bit di tale campo,
k
l'intervallo di possibili numeri di sequenza [0, 2 -1] . Avendo un intervallo finito di numeri di sequenza, tutte le
k
operazioni aritmetiche devono essere effettuate modulo 2 . Lo spazio dei numeri di sequenza pu essere pensato
k
k
come un insieme ciclico di 2 elementi in cui il numero di sequenza 2 -1 immediatamente seguito da 0.
Vedremo che TCP ha un campo a 32 bit per i numeri di sequenza, e che i numeri di sequenza TCP contano i byte nello
stream anzich i pacchetti.
Il mittente GBN deve rispondere a tre tipi di evento:

invocazione dall'alto: quando un'applicazione dall'altro chiede l'invi di un pacchetto, come prima cosa il mittente
controlla se la finestra piena, ossia se vi sono N pacchetti in sospeso senza notifica. Se la finestra non piena, crea
e invia un pacchetto e le variabili vengono aggiornate adeguatamente. Se la finestre piena il mittente restituisce i
dati a livello superiore che manterr questo dato nei buffer o implementer un meccanismo di sincronizzazione
ricezione di un ACK: un acknowlegement cumulativo indica che tutti pacchetti con un numero di sequenza minore
o uguale a n sono stati correttamente ricevuti dal destinatario
evento di timeout: quando si verifica un timeout, il mittente invia nuovamente tutti i pacchetti spediti che ancora
non hanno riscontro. Se si riceve un'ACK ma ci sono ancora pacchetti aggiuntivi trasmessi non riscontrati, il timer
viene fatto ripartire. Se, invece, non ci sono pacchetti in sospeso in attesa di riscontro, il contatore viene fermato.

Anche le azioni del destinatario GBN sono semplici. Se un pacchetto con numero di sequenza n viene ricevuto
correttamente ed in ordine, il destinatario manda un ACK per quel pacchetto. In tutti gli altri casi, il destinatario
scarta i pacchetti e rimanda un ACK per il pacchetto in ordine ricevuto pi di recente. Quindi nel nostro protocollo, il
destinatario scarta i pacchetti fuori sequenza. Il vantaggio di questo approccio la semplicit: il destinatario non deve
salvare nel buffer i pacchetti che giungono fuori sequenza.

RIPETIZIONE SELETTIVA
Quando la dimensione della finestra e il prodotto larghezza di banda-ritardo sono entrambi grandi, nella pipeline
possono trovare numerosi pacchetti. Un errore su un solo pacchetto pu pertanto provocare la ritrasmissione di un
elevato numero di pacchetti, in molti casi inutile.
I protocolli a ripetizione selettiva (SR, selective-repeat protocol) evitano le ritrasmissione non necessarie forzando il
mittente a ritrasmettere solo quei pacchetti su cui esistono sospetti di errore presso il destinatario (ogni pacchetto
deve avere un proprio timer logico, dato che al timeout sar ritrasmesso un solo pacchetto). Questo costringe il
destinatario a mandare riscontri specifici per i pacchetti ricevuti in modo corretto. Si user nuovamente una
dimensione di finestra pari a N ma, a differenza di GBN, il mittente avr gi ricevuto agli ACK di qualche pacchetto
nella finestra.
Il destinatario SR invier un riscontro per i pacchetti correttamente ricevuti sia in ordine sia fuori sequenza. Questi
vengono bufferizzati finch non sono stati ricevuti tutti pacchetti mancanti. Non sempre il mittente e il destinatario
hanno la stessa visuale su cosa stato ricevuto correttamente: le finestre del mittente e del destinatario non sempre
coincidono.

importante notare che, se il destinatario riceve un pacchetto con numero di sequenza minore della base della sua
finestra, si deve generare un ACK anche se si tratta di un pacchetto che il ricevente ha gi riscontrato. Questo perch,
se tra destinatario e mittente non si propaga un ACK per il pacchetto send_base, il mittente potrebbe ritrasmetterlo

10

anche se chiaro che il destinatario lo ha gi ricevuto. Se il destinatario non inviasse un riscontro per questo
pacchetto, la finestra del mittente non avanzerebbe.
La mancanza di sincronizzazione tra finestre del mittente e del destinatario ha conseguenze importanti quando
abbiamo a che fare con la realt di un intervallo finito di numeri di sequenza. Consideriamo un intervallo di quattro
numeri di sequenza per i pacchetti (0, 1, 2, 3) una dimensione di finestra pari a 3. Supponiamo che pacchetti 0,1 e 2
vengano trasmessi e ricevuti correttamente, e che il destinatario li riscontri.
Consideriamo ora due scenari:
1.
2.

gli ACK dei primi tre pacchetti vanno persi e il mittente ritrasmette i pacchetti; il destinatario riceve quindi un
pacchetto con numero di sequenza zero, copia nel primo pacchetto inviato.
gli ACK dei primi tre pacchetti vengono tutti consegnati correttamente ma il pacchetto con numero di
sequenza 3 va perso.

Dal punto di vista del destinatario i tre scenari sono uguali, non esiste modo per distinguere la ritrasmissione del
primo pacchetto dalla trasmissione originaria delle quinto. Chiaramente, una dimensione di finestra inferiore di uno
rispetto a quella dello spazio dei numeri di sequenza non funzioner. La finestra deve avere dimensioni inferiori o
uguale alla met dello spazio dei numeri di sequenza dei protocolli SR.

3.4 TRASPORTO ORIENTATO ALLA CONNESSIONE - TCP


TCP viene detto orientato alla connessione perch, prima di scambiarsi dati, i processi devono effettuare l'handshake.
Come parte dell'instaurazione della connessione TCP, entrambi i lati inizia rizzeranno molte variabili di stato. Il
protocollo in questione va in esecuzione solo sui sistemi terminali e non degli elementi di rete intermedi (router e
commutatori a livello di link), questi ultimi non salvano lo stato della connessione TCP. Infatti, il router intermedi sono
completamente ignari della connessione TCP; essi vedono datagrammi, non connessioni.
Una connessione TCP offre un servizio full-duplex: il flusso di dati tra due o all'orlo zoofilo o su e lo meno e a livello di
applicazione pu verificarsi contemporaneamente nelle due direzioni. Una connessione TCP anche punto-punto,
ossia ha luogo tra un singolo mittente e un singolo destinatario. Il cosiddetto molticast, ossia il trasferimento di dati da
un mittente a molti destinatari in un unico operazione d'invio, con una TCP non possibile.
Supponiamo che, il client voglia inizializzare una connessione con il processo server. Il client applicativo informa il
livello di trasporto client di voler stabilire una connessione verso un processo nel server. Il livello di trasporto nel client
procede quindi a stabilire una connessione con il TCP nel server. I due host instaurano una connessione detta
handshake a tre vie (three-way handshake).

11

Il client manda un flusso di dati attraverso la socket, TCP dirige i dati al buffer d'invio della connessione, uno dei buffer
che viene riservato durante l'iniziale handshake a tre vie. La massima quantit di dati che possono essere prelevati e
posizionati in un segmento viene limitata dalla dimensione massima di segmento (MSS, maximum segment size).
Questo valore viene generalmente impostato determinando prima la lunghezza del frame pi grande a livello di link
che pu essere rinviato dall'host mittente locale, la cosiddetta unit trasmissiva massima (MTU, maximum
transmission unit) e poi scegliendo MSS per assicurarsi che il segmento TCP (una volta incapsulato in un datagramma
IP) stia all'interno di un singolo frame a livello di link. Si noti che MSS rappresenta la massima quantit di dati a livello
di applicazione del segmento, e non la massima dimensione del segmento TCP con intestazioni incluse. TCP accoppia
ogni porzione di dati client con l'intestazione TCP, andando pertanto a formare segmenti TCP. Ogni lato della
connessione presenta un proprio buffer d'invio e di ricezione.

Il segmento TCP consiste di campi di intestazione e di un campo che contiene dati applicativi. Quando TCP invia un file
di grandi dimensioni, il protocollo frammenta da fare in porzioni di dimensione MSS. Le applicazioni interattive,
invece, trasmettono spesso porzioni di dati pi piccole di MSS.
L'intestazione TCP occupa comunemente 20 byte; come in UDP, l'intestazione include

numeri di porta origine e destinazione, utilizzati per il multiplexing/demultiplexing dei dati da e verso le
applicazioni del livello superiore
il campo numero di sequenza, a 32 bit, identifica, nello stream di byte del trasmettitore, la posizione dei dati nel
segmento. Questo valore riferito allo stream che fluisce nella medesima direzione del segmento, mentre il
numero di riscontro si riferisce allo stream che fluisce nella direzione opposta;
il campo numero di riscontro, a 32 bit, contiene il numero sequenziale del byte successivo a quello correttamente
ricevuto dalla destinazione. Tale campo valido solo nei segmenti di riscontro, o ne i segmenti utilizzanti la tecnica
trasmissiva piggy-backing, e fa riferimento allo stream di dati che fluisce nella direzione opposta a tale segmento;
il campo lunghezza dell'intestazione (HLEN), a 4 bit, specifica la lunghezza dell'intestazione TCP in parole da 32 bit.
L'intestazione TCP ha lunghezza variabile a causa del campo delle opzioni TCP. Generalmente, il campo delle
opzioni vuoto, e quindi la lunghezza consueta di 20 byte;
il campo flag comprende 6 bit. Il bit ACK viene usato per indicare che il valore trasportato nel campo di riscontro
valido; ossia, il segmento contiene un riscontro per un segmento che stato ricevuto con successo. I bit RST, SYN
FIN vengono utilizzati per impostare e chiudere la connessione. Se il bit PSH ha valore 1, il destinatario dovrebbe
inviare immediatamente i dati al livello superiore. Infine, si utilizza il bit URG per indicare nel segmento la presenza
di dati che l'entit mittente al livello superiore ha marcato come urgenti.
il campo finestra di ricezione, numero intero senza segno a 16 bit, viene utilizzato per il controllo del flusso;
specifica la dimensione dell'buffer che il TCP a disposizione per immagazzinare dati in arrivo; utilizzato per la
gestione dinamica della dimensione della finestra scorrevole
campo checksum, 16 bit, contenente un valore intero utilizzato dal TCP della macchina host di destinazione, per
verificare l'integrit dei dati e la correttezza dell'intestazione; per il calcolo del valore checksum il TCP ha bisogno

12

di aggiungere una pseudointestazione al datagramma, per effettuare cos un controllo anche sugli indirizzi IP di
destinazione e provenienza.
il campo puntatore ai dati urgenti, a 16 bit, se valido, questo campo conterr un puntatore alla posizione, nello
stream, dei dati non urgenti (ultimo byte dei dati urgenti
Nella pratica, PSH, URG e il puntatore non vengono usati.
il campo opzioni, facoltativo e di lunghezza variabile, viene utilizzato quando mittente e destinatario negoziano la
dimensione massima del segmento (MSS) o come fattore di scala della finestra nelle reti ad alta velocit. Viene
inoltre definita l'opzione di time-stamping; le principali operazioni di TCP sono
o maximum TCP payload: durante la fase di connessione, ciascun end-point annuncia la massima
dimensione di payload che desidera accettare; la minima tra le due dimensioni annunciate viene
selezionata per la trasmissione
o window scale: per negoziare un fattore di scala per la finestra; utile per connessioni a larga banda
e/o elevato ritardo di trasmissione
o selective repeate: nel caso in cui un segmento corrotto sia stato seguito da segmenti corretti,
introduce i NAK per permettere al receiver di richiedere la ritrasmissione di quello specifico
segmento; un'alternativa al Go-back-n, che prevede la trasmissione di tutti i segmenti

Due tra i campi pi importanti dell'intestazione di segmento TCP contengono il numero di sequenza e il numero di
riscontro che rappresentano una parte critica del servizio di trasferimento dati affidabile proprio di TCP. TCP vede i
dati come un flusso di byte non strutturati, ma ordinati. L'uso dei numeri di sequenza in TCP riflette questa visione,
dato che i numeri di sequenza si applicano al flusso di byte trasmessi e non alla serie dei segmenti trasmessi. Il
numero di sequenza per un segmento pertanto il numero nel flusso di byte del primo byte del segmento. Ad
esempio, supponiamo che un processo nel'host A numeri implicitamente ogni byte del flusso di dati. Ipotizziamo che il
flusso di dati consista in un file da 500.000 byte, che MSS valga 1000 byte e che il primo byte del flusso sia numerato
con 0. TCP costruisce 500 segmenti per questo flusso di dati. Al primo segmento viene assegnato numero di sequenza
0, al secondo 1000, al terzo 2000 e cosi via. Prendiamo ora in considerazione i numeri di riscontro. TCP full-duplex e,
di conseguenza, l'host A pu contemporaneamente inviare ricevere dati dall'host B. Il numero di riscontro che l'host A
riceve nei propri sentimenti il numero di sequenza dei byte successivo che l'host A attende da B. Supponiamo che
l'host A abbia ricevuto da B tutti i byte numerati da 0 a 535, e che A stia per mandare un segmento all'host B. L'host A
in attesa del byte 536 e dei successivi byte nel flusso di dati di B. Pertanto, l'host A scriver 536 nel campo del
numero di riscontro del segmento che spedisce a B.
Come ulteriore esempio, supponiamo che l'host A abbia ricevuto il segmento dall'host B contenente i byte da 0 a 535
e un altro segmento contenente i byte da 900 a 1000. Per qualche motivo l'host A non ha ancora ricevuto il byte da
536 a 899. Perci il prossimo segmento di A destinato a B conterr 536 nel campo numero di riscontro. Dato che, TCP
effettua il riscontro solo dei byte fino al primo byte mancante nel flusso, si dice che tale protocollo offre riscontri
cumulativi. Negli esempi abbiamo ipotizzato che il numero di sequenza iniziale fosse 0. In verit, i lati della

13

connessione TCP scelgono a caso un numero di sequenza iniziale. Ci minimizza la possibilit che un segmento, ancora
presente nella rete per via di una connessione tra due host precedente e gi terminata, venga interpretato
erroneamente come segmento valido in una connessione successiva per gli stessi due host.

STIMA DEL ROUND TRIP TIME E TIMEOUT


TCP utilizza un meccanismo di timeout e ritrasmissione per ripristinare i segmenti perduti. Il timeout dovrebbe essere
pi grande del tempo di andata e il ritorno della connessione (RTT - round trip time). L'RTT misurato di un segmento,
chiamato SampleRTT, la quantit di tempo che intercorre tra l'istante d'invio del segmento quello di ricezione
dell'ACK del segmento. La maggior parte delle implementazioni TCP considera un solo valore di SampleRTT alla
volta. Ossia, in ogni istante di tempo, il SampleRTT viene stimato per uno solo dei segmenti trasmessi e ancora
riscontrati, il che comporta approssimativamente un nuovo valore di SampleRTT a ogni RTT. Inoltre, TCP non calcola
mai il SampleRTT per i segmenti ritrasmessi. Ovviamente, i campioni variano a causa della congestione nei router e
al diverso carico sui sistemi terminali. A causa di tale fluttuazione, ogni valore di SampleRTT pu essere atipico. Per
stimarne uno tipico, risulta naturale effettuare una media, che in TCP chiamata estimatedRTT. Quando si ottiene
un nuovo SampleRTT, TCP aggiorna la media secondo la formula:
EstimatedRTT = (1- ) * EstimatedRTT + * SampleRTT
il valore raccomandato per 0,125 (ossia 1/8); tale media attribuisce maggiore importanza ai campioni recenti
rispetto a quelli vecchi, una media costruite in tal modo detta media mobile esponenziale ponderata (EWMA,
exponential weighted moving avarage). La parola esponenziale compare in quanto il peso dei campioni decresce
esponenzialmente al procedere degli aggiornamenti. Oltre ad avere una stima di RTT anche importante possedere la
misura della variabilit DevRTT:
DevRTT = (1-)*DevRTT + *|SampleRTT - EstimatedRTT|
Si noti che DevRTT un EWMA della differenza tra SampleRTT e EstimatedRTT.
L'intervallo di time auto non pu essere inferiore a quello di media, ma non dovrebbe essere molto maggiore:
TimeoutInterval = EstimatedRTT + 4*DevRTT

14

Se tutto ci funziona bene in teoria, la gestione dei timer pu richiedere overhead considerevoli. Pertanto, le
procedure suggerite per la gestione di timer TCP utilizzano un solo timer di ritrasmissione, anche in presenza di
segmenti trasmessi ma ancora riscontrati.
Esistono tre eventi principali relativi alla trasmissione e
ritrasmissione
dei
dati:
dati
provenienti
dall'applicazione, a eccezione di a. Quando si verifica
il primo evento, TCP incapsula i dati che gli giungono
dell'applicazione in un segmento che la passa a IP.
Inoltre, se non gi in funzione per qualche altro
sentimento, TCP avvia il timer quando il segmento
passa a IP. utile pensare che il timer si associato al pi
vecchio segmento non riscontrato. L'intervallo di
scadenza per il timer il TimeOutInterval, che
viene calcolato in termini di EstimatedRTT e
DevRTT. Il secondo evento il Timeout, cui TCP
risponde ritrasmettendo il segmento che lo ha causato,
e poi riavvia il timer. Il terzo evento gestito dal mittente
TCP, l'arrivo del segmento di riscontro con un valore
valido nel campo ACK. Quando si verifica tale evento,
TCP confronta il valore di a ACK y con la propria
variabile SendBase. Come precedentemente indicato,
TCP utilizza riscontri cumulativi, e y riscontra la
ricezione di tutti byte precedenti al byte numero y.
Consideriamo degli scenari possibili e analizziamo il comportamento di TCP:

15

l'host A spedisce un segmento all'host B. Supponiamo che


questo segmento abbia numero di sequenza 92 e contenga 8
byte di dati. Dopo aver inviato il segmento, A attende un
segmento da B con un numero di riscontro 100. Sebbene il
segmento in questione sia stato ricevuto da B, il riscontro sul
percorso inverso viene smarrito. In questo caso, si verifica
l'evento di timeout, e l'host A ritrasmette lo stesso segmento.
Ovviamente, quando l'host B riceve la ritrasmissione, rileva dal
numero di sequenza del segmento che contiene dati che sono
gi stati ricevuti. Quindi TCP nell'host B scarter i byte del
secondo ritrasmesso.
L'host A invia due segmenti. Il primo ha numero di sequenza
92 e 8 byte di dati, e il secondo con numero di sequenza 100 e
20 byte di dati; supponiamo che entrambi arrivino intatti a B, e
che questo invii due riscontri separati per i segmenti, il primo
numerato 100, il secondo 120. Supponiamo ora che nessuno
dei riscontri arrivi all'host A prima del timeout. Quando si
verifica il timeout, l'host A rispedisce il primo segmento con
numero di sequenza 92 e riavvia il timer. Fino a quando l'ACK
del secondo segmento non arriva prima del nuovo timeout, il
secondo segmento non sar ritrasmesso.
L'host A invia due segmenti, esattamente come nell'esempio
precedente. Il riscontro del primo segmento viene perso nella
rete ma, appena prima dell'evento di timeout, l'host A riceve
un riscontro con numero 120. pertanto a conoscenza che
l'host B ha ricevuto tutto fino al byte 119; e quindi non
rispedisce nessuno dei due segmenti.

VARIANTI DI TCP
Consideriamo ora alcune varianti utilizzate dalla maggior parte dell'implementazione TCP. La prima riguarda la
lunghezza dell'intervallo di timeout la seconda la ritrasmissione dei pacchetti.
RADDOPPIO DELL'INTERVALLO DI TIMEOUT: con questa modifica in tutti i casi in cui si verifica un timeout, TCP
ritrasmette il segmento non ancora riscontrato con il pi piccolo numero di sequenza, ma imposta il successivo
intervallo di timeout al doppio del valore precedente, anzich derivarlo dagli ultimi EstimatedRTT e DevRTT. Di
conseguenza gli intervalli crescono esponenzialmente a ogni ritrasmissione. Comunque, tutte le volte che il timer
viene avviato dopo uno dei due eventi (ossia alla ricezione dei dati dall'applicazione superiore e la ricezione di ACK), il
tempo di timeout viene ricavato dai pi recenti valori di. Questa modifica offre una forma illimitata di controllo di
congestione: la scadenza del timer viene probabilmente causata dalla congestione nella rete, ossia tra i pacchetti
arrivano presso una coda dell'utente nel percorso tra l'origine della destinazione, provocando l'eliminazione dei
pacchetti e/o lunghi ritardi di accomodamento.
RITRASMISSIONE RAPIDA: uno dei problemi legati alle ritrasmissione che il periodo di timeout pu rivelarsi
relativamente lungo. Quando si smarrisce un segmento, questo lungo periodo di timeout impone al mittente di
ritardare il nuovo rinvio del pacchetto perso. Fortunatamente il mittente pu spesso rilevare la perdita dei pacchetti
ben prima che si verifichi l'eventualit grazie a ACK duplicati. Quando il destinatario TCP riceve un segmento con

16

numero di sequenza superiore al prossimo numero di sequenza atteso e in ordine, rileva un buco nel flusso di dati,
ossia un segmento mancante. Tale vuoto potrebbe essere il risultato di segmenti tersi o riordinate all'interno della
rete. Il destinatario non pu inviare un riscontro negativo esplicito al mittente, dato che TCP non lo prevede, ma si
limita a riscontrare di nuovo l'ultimo byte di dati che ha ricevuto in ordine (duplicando cos un ACK). Se un segmento
viene smarrito ci saranno probabilmente molti ACK duplicati. Se il mittente TCP riceve tre ACK duplicati dello stesso
dato, considera quest'evento come indice che il segmento che segue il segmento riscontrato tre volte andato
perduto. Nel caso in cui siano stati ricevuti tre ACK duplicati, il mittente TCP effettua una ritrasmissione rapida,
disponendo il segmento mancante prima che scada il timer.

GESTIONE DELLA CONNESSIONE TCP


Stabilire connessioni TCP aggiunge ritardi percepiti da chi naviga nel Web. Inoltre molti attacchi in rete sfruttano la
vulnerabilit nella gestione della connessione TCP. Il TCP nel client quindi procedere stabilire una connessione TCP con
il TCP nel server nel seguente modo:
1.

2.

TCP sul lato client invia una speciale segmento al TCP sul lato server. Questo
segmento speciale non contiene dati ma uno dei bit nell'intestazione, il bit SYN,
posto a 1. Per questo motivo, il segmento viene detto segmento SYN. Il client
sceglie a caso un numero di sequenza iniziale e lo pone nel campo numero di
sequenza del segmento SYN iniziale.
Quando il datagramma IP contenente il segmento TCP SYN arriva all'host server, il
server estrae il segmento dal datagramma, alloca il buffer e le variabili TCP alla
connessione e invia un segmento di connessione garantita al client TCP. Nella sua

17

3.

intestazione vi sono tre informazioni importanti: SYN posto a 1, il campo di riscontro assume il valore client
client_isn+1, il server sceglie il proprio numero di sequenza iniziale e lo pone nel campo numero di
sequenza. Il segmento di connessione garantita viene talvolta detto segmento SYNACK.
Alla ricezione del segmento SYNACK, il client alloca buffer e variabile alla connessione. L'host client invia al
server un altro segmento ponendo il valore server_isn+1 nel campo di riscontro dell'intestazione del
segmento TCP. Il bit SYN posto a zero, dato che la connessione stata stabilita.

I due host si scambiano tre pacchetti, per questo motivo, questa procedura viene detta handshake a tre vie.
Ciascuno dei processi che partecipano alla connessione pu terminarla: supponiamo che il client decide di
chiedere la connessione, invier un comando di chiusura nella cui intestazione troviamo il cosiddetto bit FIN con
valore 1; quando il server riceve questo segmento, risponde inviandone uno di riscontro al client, segmento di
shutdown, con il bit FIN=1.

Nella prima connessione TCP, i protocolli TCP in esecuzione degli host assumono vari Stati TCP. Una volta spedire
segmento SYN, il client TCP entra nello stato SYN_SENT, durante il quale attende dal server TCP un segmento con
un riscontro. Una volta ricevuta, il client TCP entra nello stato ESTABLISHED. Supponiamo che il client decide di
voler chiudere la connessione, inviando un segmento con il bit FIN impostato a 1, entra nello stato FIN_WAIT_1. Il
client TCP attende dal server un segmento con un riscontro e, quando riceve, entra nello stato FIN_WAIT_2, in cui
il client attende un altro segmento dal server con bit FIN impostato a 1. Dopo aver ricevuto questo segmento, il
client TCP lo riscontra ed entra nello stato TIME_WAIT, che consente al client TCP di inviare nuovamente l'ultimo
riscontro nel caso in cui l'ACK venga perduto. Il tempo trascorso in questo ultimo stato vada 30 secondi a due
minuti, dipende dall'implementazione utilizzata. Dopo l'attesa, la connessione formalmente si chiude e tutte le
risorse sul lato client vengono rilasciate.

18

3.5 CONTROLLO DI FLUSSO E CONTROLLO DI CONGESTIONE

Gli host agli estremi delle connessioni TCP impostano di buffer di ricezione della connessione. Quando la connessione
TCP e riceve byte corretti e in sequenza, l'imposizione nel buffer di ricezione. Processo applicativo associato leggera ai
dati da questo buffer, ma non necessariamente nell'istante in cui arrivano. Se la relazione relativamente lenta nella
lettura dei dati, pu accadere che il mittente mandi in overflow il buffer di ricezione.
TCP offre un servizio di controllo del flusso alle applicazioni per scongiurare questa eventualit. Il controllo del flusso
pertanto un servizio di confronto sulle velocit, dato che paragona la frequenza d'invio del mittente con quella di
lettura dell'applicazione ricevente. Come notato in precedenza, il mittente TCP possono anche essere rallentati dalla
congestione della rete IP. Questa forma di controllo del mittente viene detta controllo di congestione. Sebbene le
azioni intraprese dal controllo di flusso e di congestione siano simili (il rallentamento del mittente), sono causate da
ragioni molto differenti.

CONTROLLO DEL FLUSSO


TCP offre controllo del flusso facendo mantenere al mittente una variabile chiamata finestra di ricezione (receive
window) che in sostanza fornisce al mittente un'indicazione dello spazio libero disponibile nel buffer del destinatario.
Dato che TCP full-duplex, i due emittenti mantengono finestre di ricezione distinte. Supponiamo che l'host A stia
inviando un file di dimensioni ragguardevoli all'host B su una connessione TCP. Quest'ultimo alloca un buffer di
ricezione per la connessione; memorizziamo la sua dimensione in RcvBuffer. Di tanto in tanto, il processo
applicativo nell'host B legge dal buffer. Definiamo le seguenti variabili.

LastByteRead: numero dell'ultimo byte nel flusso di dati letto a partire dal buffer da parte del processo
applicativo in B;
LastByterRcvd: numero dell'ultimo byte nel flusso di dati che proviene dalla rete e che stato copiato
nel buffer di ricezione in B.

Dato che TCP non pu fuoriuscire dalla buffer allocato, dobbiamo avere
LastByterRcvd - LastByteRead RcvBuffer
La finestra di ricezione, chiamata RcvWindow, viene impostata alla quantit di spazio disponibile nel buffer:
RcvWindow = RcvBuffer - [LastByterRcvd - LastByteRead]
La RcvWindow dinamica. L'host B comunica all'host A quanto spazio disponibile presente nel buffer della
connessione posizionando il proprio valore corrente di RcvWindow nel campo finestra di ricezione dei segmenti che
manda ad A. L'host B inizializza RcvWindow con il valore di RcvBuffer . A sua volta, l'host A tiene

19

traccia di due variabili, LastByterSent e LastByteAcked, la differenza tra il valore di queste due variabili,
esprime la quantit di dati non ancora riscontrati spediti da A nella connessione. Mantenendo la quantit di dati non
riscontrati sotto il valore di RcvWindow, si garantisce che l'host A non mandi in overflow il buffer di ricezione
presso l'host B. Quindi, l'host A si assicura il per tutta la durata della connessione sia rispettata disuguaglianza:
LastByterSent - LastByteAcked RcvWindow

In questo schema esiste un problema tecnico secondario.


Supponiamo che il buffer di ricezione dell'host B si riempia, di
modo che RcvWindow =0 e che, dopo averlo notificato all'host
A, non abbia pi nulla da inviare ad A. Quando il processo
applicativo in B svuota il buffer, TCP non invia nuovi segmenti
con nuovi valori di RcvWindow; infatti, TCP fa pervenire un
segmento all'host A solo se ha dati o un riscontro da mandare.
Di conseguenza quest'ultimo non viene informato del fatto che
si sia liberato un po' di spazio nel buffer di ricezione dell'host B:
l'host A bloccato e non pu trasmettere ulteriori dati. Per
risolvere questo problema, le specifiche TCP richiedono che
l'host A continui a inviare segmenti con un byte di dati quando
la finestra di ricezione di B zero. Questi segmenti verranno
riscontrati dal destinatario. Si pu verificare che il buffer inizia
svuotarsi e i riscontri conterranno un valore non nullo di
RcvWindow.
La silly window syndrome (sindrome da finestra sciocca, abbreviata con SWS) un problema legato alla cattiva
implementazione del controllo di flusso a livello TCP. Un processo di scrittura molto lento da parte del mittente nel
buffer di trasmissione (o di lettura da parte del ricevente) porta infatti all'invio di segmenti di dati molto piccoli,
aumentando cos il rapporto tra header e dati con un conseguente uso inefficiente del canale.

Sindrome causata dal mittente: Nel caso in cui il processo di scrittura dei dati nel buffer TCP del mittente sia molto
lento, il protocollo spedir una serie di pacchetti contenenti una quantit di dati molto bassa, con un uso
inefficiente del canale. La soluzione a questo problema consiste nel trattenere i dati nel buffer allo scopo di spedirli
in un unico segmento. Tuttavia un'attesa troppo lunga potrebbe causare dei ritardi troppo grandi nella
trasmissione. Un'ottima soluzione a questo problema fornita dall'algoritmo di Nagle, secondo il quale i dati
devono essere accumulati nel buffer per poi venire spediti in un unico blocco alla ricezione dell'ACK dell'ultimo
pacchetto trasmesso o quando si raggiunge la massima dimensione fissata per un segmento (MSS). Questo
semplicissimo algoritmo riesce a risolvere il problema tenendo anche conto della velocit di trasmissione dei
pacchetti: se questa pi lenta della scrittura dei messaggi (il mittente riesce ad accumulare una notevole quantit
di dati nel buffer prima dell'arrivo del riscontro) vengono creati pacchetti con il massimo rapporto dati/header,

20

sfruttando al meglio le risorse del canale. Se invece la rete pi veloce, i pacchetti risulteranno pi piccoli,
assicureranno una certa continuit nella trasmissione e verr garantito comunque un utilizzo pi efficiente delle
risorse del canale che nel caso in cui l'algoritmo non venga utilizzato.
Sindrome causata dal ricevente: Nel caso sia invece il ricevente a leggere lentamente i pacchetti ricevuti, il buffer
in ingresso tender a riempirsi, costringendo a richiedere al mittente di interrompere la trasmissione. Non appena
una trama viene letta il mittente viene informato dal riscontro che si liberato dello spazio nel buffer, e reagisce
cos inviando un nuovo segmento. Si viene cos a creare una situazione dove viene generato un nuovo pacchetto
non appena si libera spazio sufficiente nel buffer, dando nuovamente origine ad una situazione di uso inefficiente
del canale dato dal cattivo rapporto lunghezza pacchetto/dati contenuti. Una possibilit adottare la soluzione di
Clark, con la quale si "inganna" il mittente specificando nei messaggi di riscontro che il buffer ancora pieno
(costringendolo cos a bloccare l'invio) fino a che la coda non si sia svuotata per met o a sufficienza per accogliere
un segmento di dimensioni massime (MSS).
Un'altra soluzione consiste nel ritardare l'invio degli ACK (bloccando cos il mittente) finch non si liberano un certo
numero di byte nel buffer. Il tempo massimo di ritardo dei riscontri va per calcolato accuratamente, per evitare
che il mittente vada in timeout e ritrasmetta il pacchetto.

PRINCIPI DI CONTROLLO DI CONGESTIONE

Consideriamo due scenari.


DUE MITTENTI, DUE RICEVENTI E UN ROUTER CON BUFFER ILLIMITATI: lhost A sta spedendo dati ad una frequenza
media di byte/sec. Tali dati sono originari, nel senso che sono spediti una sola volta, non sono previste perdite e
quindi non ci sono ritrasmissioni. Lhost B opera in modo simile trasmettendo contemporaneamente ad A dati alla
stessa frequenza . I pacchetti transitano per un router e un collegamento condiviso che ha capacit R. Il throughput
per connessione (ovvero il numero di byte per secondo al ricevitore) equivale alla frequenza di invio del mittente
(tutto quello che viene trasmesso dal mittente arriva al ricevente con un ritardo finito) finch questa frequenza non
raggiunge il valore R/2. Questo limite superiore sul throughput conseguenza della condivisione della capacit di

21

collegamento tra le due connessioni. Quando la


frequenza di invio si avvicina a R/2, il ritardo medio
cresce sempre di pi; quando supera R/2, il numero
medio di pacchetti in coda cresce senza limite e il
ritardo di consegna tende allinfinito. Di conseguenza,
avere un throughput aggregato vicino a R potrebbe
sembrare lideale in termini di throughput ma non lo
certo dal punto di vista del ritardo: quando la
frequenza di arrivo dei pacchetti si avvicina alla
capacit del collegamento, si rilevano lunghi ritardi di
accodamento.
DUE MITTENTI, DUE RICEVENTI E UN ROUTER CON BUFFER FINITI: assumiamo che la dimensione del buffer del router
sia finita, i pacchetti che giungono in un buffer gi pieno saranno scartati. Quando questo accade, supponendo che la
trasmissione sia affidabile, il mittente ritrasmetter il pacchetto perduto. Bisogna quindi fare una distinzione tra la
frequenza di invio di dati originari, che indichiamo con , e il tasso di trasmissione con il quale il livello di trasporto
invia segmenti (originari e ritrasmessi) sulla rete, che indichiamo con * e chiamiamo carico offerto alla rete. Le
prestazioni, a questo punto, dipenderanno fortemente da come si effettua la ritrasmissione.
Consideriamo il caso in cui il mittente rispedisce solo
se sicuro che il pacchetto sia andato perduto.
Supponiamo che il carico offerto * valga R/2, di
questi, in media, solo R/3 costituisce traffico di dati
originari poich il mittente deve effettuare
ritrasmissione a seguito della perdita dei pacchetti.
Consideriamo invece il caso in cui il mittente vada in
timeout prematuro: sia il pacchetto di dati originari
che quello ritrasmesso possono raggiungere il
destinatario che scarter uno dei due. Quindi il lavoro
sprecato dal router per instradare il pacchetto che
verr poi scartato occupa inutilmente parte della
capacit del collegamento. Il throughput assumer
asintoticamente il valore R/4 quando il carico offerto
tende a R/2.
Esistono due principali orientamenti al controllo di congestione utilizzati nella pratica:

Controllo della congestione end-end: lo strato di rete non fornisce alcun supporto esplicito allo strato di
trasporto per il controllo della congestione. Anche la presenza della congestione nella rete deve essere
dedotta dai terminali basandosi solo sull' osservazione del comportamento della rete (per esempio, perdita di
pacchetti e ritardi). Il TCP deve necessariamente adottare questo approccio end-to-end al controllo della
congestione, poich lo strato IP non fornisce alcun feedback riguardante la congestione della rete ai
terminali. Il segmento TCP perso (come indicato da un timeout o da un triplo duplicato del riscontro)
assunto come indice di congestione della rete e il TCP diminuisce di conseguenza le dimensioni della finestra.
Controllo della congestione assistito dalla rete: i componenti dello strato di rete (i router) forniscono al
sender un feedback esplicito relativo allo stato di congestione nella rete. Questo feedback pu essere
semplicemente un singolo bit che indica la congestione a un link. Questo approccio adottato nelle prime
architetture SNA dell'IBM e DECnet della DEC, stato recentemente proposto per le reti TCP/IP ed usato
per il controllo della congestione nell'Available Bit-Rate (ABR). Una forma di controllo della congestione usata
per l'ABR dell'ATM permette a un router di informare esplicitamente il sender della velocit di trasmissione
che esso (il router) pu supportare su un link in uscita.

22

CONTROLLO DELLA CONGESTIONE TCP


Lapproccio scelto da TCP consiste nellimporre a ciascun mittente un limite alla frequenza di invio sulla propria
connessione, in funzione della congestione di rete percepita. Se il mittente TCP si accorge di condizioni di scarso
traffico sul percorso che porta alla destinazione, allora incrementa il proprio tasso trasmissivo; se, invece, percepisce
traffico lungo il percorso, lo riduce. Esaminiamo lalgoritmo Reno, utilizzato nei pi moderni sistemi operativi, e
supponiamo che si stia trasmettendo un file di grandi dimensioni. Il meccanismo di controllo della congestione fa
tener traccia ai terminali di una variabile aggiuntiva, la finestra di congestione, detta CongWin, che impone un
vincolo alla frequenza di immissione di traffico sulla rete da parte dei mittenti TCP. Nello specifico, la quantit di dati
non riscontrati da un mittente non pu eccedere il minimo tra i valori di CongWin e RcvWindow:
LastByteSent - LastByteAcked min{ CongWin, RcvWindow}

Assumiamo che il buffer di ricezione sia sufficientemente capiente da poter ignorare il vincolo della finestra di
ricezione. In questo caso, la quantit di dati non riscontrati che un host pu avere all'interno di una connessione TCP
limitata unicamente attraverso CongWin.
Quindi, approssimativamente, all'inizio di ogni tempo di round-trip (RTT), il limite sopra esposto permette al mittente
di inviare CongWin byte di dati nella connessione, e alla fine del RTT il mittente riceve i riscontri per i dati. Quindi il
ritmo di invio del mittente circa CongWin/RTT byte/s. Variando il valore di Congwin, il mittente pu quindi variare il
ritmo a cui manda i dati nella sua connessione.
Consideriamo poi in che modo un mittente TCP percepisce che c' congestione nel percorso tra s e la destinazione.
Definiamo un "evento di perdita" a un mittente TCP come il verificarsi o di un timeout o della ricezione di tre ACK
duplicati dal ricevente. Quando c' congestione eccessiva, uno (o pi) buffer dei router lungo il percorso vanno in
overflow, causando la perdita di datagrammi. Il datagram eliminato, a sua volta, d luogo a un evento di perdita al
mittente che considerato dal mittente come un' indicazione di congestione nel percorso dal mittente al ricevente.
Avendo considerato come viene rilevata la congestione, consideriamo il caso di una rete priva di congestione in cui
non si verificano smarrimenti. In questo scenario, i riscontri per i segmenti precedentemente non riscontrati verranno
ricevuti dal mittente TCP. Il TCP considera larrivo di tali riscontri come un indicazione del successo con cui sono giunti
i pacchetti a destinazione, e utilizza i riscontri per aumentare l dimensioni della propria finestra di congestione e di
conseguenza la frequenza trasmissiva. Notiamo che, se i riscontri arrivano con frequenza relativamente bassa, allora la
finestra di congestione verr ampliata piuttosto lentamente, se invece arrivano ad alta frequenza la finesra si amplier
piu velocmente. Dato che TCP utilizza i riscontri per scatenare o temporizzare gli incrementi della dimensione della
finestra di congestione, si dice che TCP Auto-temporizzante.
L algoritmo di controllo della congestione di TCP ha tre componenti principali: (i) incremento additivo, decremento
moltiplicativo, (ii) partenza lenta (slow start) e (iii) reazione a eventi di timeout.

23

INCREMENTO ADDITIVO, DECREMENTO MOLTIPLICATIVO


L'idea alla base del controllo di congestione di TCP quella di far ridurre al mittente il suo ritmo di invio (diminuendo
la dimensione della sua finestra di congestione, CongWin) quando si verifica un evento di perdita. Dal momento che
altre connessioni TCP che stanno passando attraverso gli stessi router congestionati sperimenteranno probabilmente
eventi di perdita, anche loro probabilmente ridurranno i loro ritmi di invio diminuendo i loro valori di CongWin.
L'effetto globale, quindi, che le sorgenti che hanno percorsi che attraversano i router congestionati riducono il ritmo
a cui inseriscono traffico nella rete, il che dovrebbe alleviare la congestione nei router congestionati.
Il TCP usa un approccio detto a "decremento moltiplicativo", che dimezza il valore corrente di CongWin dopo un
evento di perdita. Quindi, se il valore di CongWin di 20 kbyte e si verifica una perdita, CongWin viene dimezzato a 10
kbyte. Se si verifica un'altra perdita, CongWin viene ulteriormente ridotto a 5 byte. Il valore di CongWin pu
continuare a scendere, ma non pu scendere sotto a 1 MSS.
TCP diminuisce il suo ritmo di invio se percepisce congestione e deve aumentare il suo ritmo di invio se non percepisce
congestione, cio, quando non si verificano eventi di perdita. Il motivo per aumentare il ritmo che se non si rileva
congestione, allora probabile che ci sia della banda disponibile (inutilizzata) che potrebbe essere sfruttata dalla
connessione TCP. In queste circostanze, il TCP aumenta lentamente la sua finestra di congestione, verificando con
cautela l'esistenza di ulteriore banda disponibile nel percorso da estremo a estremo. Il mittente TCP fa questo
aumentando leggermente Congw in ogni volta che riceve un ACK. Un mittente TCP aumenta la sua CongWin
approssimativamente di 1 MSS per ogni tempo di round-trip fin quando non si verificano eventi di perdita. Quindi, un
mittente TCP incrementa additivamente e decrementa
moltiplicativamente il suo ritmo di invio. Per questo motivo,
il controllo di congestione di TCP spesso definito come un
algoritmo
a
incremento
additivo,
decremento
moltiplicativo (AIMD). La fase di incremento lineare del
protocollo di controllo della congestione di TCP nota come
prevenzione della congestione (congestion avoidance). Il
valore di CongWin segue ripetutamente dei cicli durante i
quali esso cresce linearmente e poi improvvisamente
dimezza il suo valore corrente, dando origine a un
andamento a "dente di sega".
PARTENZA LENTA
Quando si inizia una connessione TCP il valore di congWin inizializzato a 1 MSS, dando luogo a un ritmo iniziale di
invio pari approssimativamente a MSS/RTT. Per esempio, se MSS = 500 byte e RTT = 200 ms, allora il ritmo di invio
iniziale solo circa 20 kbit/s. Dato che la banda disponibile per la connessione potrebbe essere molto maggiore,
sarebbe un peccato aumentare il ritmo solo linearmente, quindi un mittente TCP aumenta il suo ritmo a velocit

24

esponenziale raddoppiando il proprio valore di CongWin


ogni RTT. Il mittente TCP continua ad aumentare il suo ritmo
di invio a velocit esponenziale fino a quando si verifica un
evento di perdita, al che CongWin viene dimezzato e quindi
cresce linearmente come descritto sopra.
Quindi, durante questa fase iniziale, che chiamata
partenza lenta (slow start), il mittente TCP inizia
trasmettendo a un ritmo lento (da cui "partenza lenta") ma
aumenta il proprio ritmo di invio a velocit esponenziale. Il
mittente realizza la crescita esponenziale aumentando il
valore di CongWin di un MSS ogni volta che viene
riscontrato un segmento trasmesso. In particolare, il TCP
manda il primo segmento nella rete e aspetta il riscontro. Se questo segmento viene riscontrato prima di un evento di
perdita, il mittente TCP aumenta la finestra di congestione di un MSS e invia due segmenti della massima dimensione.
Se questi segmenti vengono riscontrati prima di un evento di perdita, il mittente TCP aumenta la finestra di
congestione di un MSS per ognuno dei segmenti riscontrati, dando una finestra di congestione di quattro MSS, e invia
quattro segmenti della massima dimensione. Questa procedura continua fino a che i riscontri arrivano prima di eventi
di perdita. Quindi, il valore di CongWin raddoppia effettivamente ogni RTT durante la fase di partenza lenta.
REAZIONE A EVENTI DI TIMEOUT
La finestra di congestione di TCP ha unascensione esponenziale crescente da 1 MSS, durante la partenza lenta, finch
si verifica un evento di perdita, con cui inizia l'andamento a dente di sega AIMD. In realt il controllo di congestione di
TCP reagisce in modo diverso a un evento di perdita rilevato attraverso un evento di timeout rispetto a un evento di
perdita rilevato tramite la ricezione di tre ACK duplicati. In questo secondo caso, il TCP si comporta come abbiamo
appena descritto: la finestra di congestione dimezzata e poi aumenta linearmente. Ma dopo un evento di timeout, il
mittente TCP entra in una fase di partenza lenta. La finestra continua a crescere esponenzialmente finch CongWin
raggiunge la met del valore che aveva prima dell'evento di timeout. A quel punto CongWin cresce linearmente.
ll TCP gestisce queste dinamiche pi complesse mantenendo una variabile chiamata Threshold (soglia), che determina
la dimensione della finestra alla quale deve terminare la partenza lenta, e deve cominciare la congestion avoidance. La
variabile Threshold inizialmente posta a un valore grande (65 kbyte in pratica) in modo che non abbia alcun effetto
iniziale. Quando si verifica un evento di perdita, il valore di Threshold posto pari alla met del valore attuale di
CongWin. Per esempio, se la finestra di congestione di 20 kbyte prima di un evento di perdita, allora il valore di
Threshold viene posto pari a 10 kbyte e conserver questo valore fino al successivo evento di perdita.
In sintesi, l'algoritmo di controllo di congestione di TCP funziona come segue:

Quando la finestra di congestione sotto la soglia, il mittente nella fase di partenza lenta e la finestra di
congestione cresce a velocit esponenziale.
Quando la finestra di congestione sopra alla soglia, il mittente nella fase di prevenzione della congestione e la
finestra di congestione cresce linearmente.
Quando si verifica un evento di perdita di tipo ACK duplicato tre volte, la soglia posta pari alla met del valore
attuale della finestra di congestione e la finestra di congestione posta pari alla soglia.
Quando si verifica un evento di perdita di tipo timeout, la soglia posta pari a met della finestra di congestione
attuale e la finestra di congestione posta pari a 1 MSS.

Una vecchia versione di TCP, nota come TCP Tahoe, taglia incondizionatamente la finestra di congestione a l MSS ed
entra nella fase di partenza lenta dopo qualunque tipo di evento di perdita. La versione pi recente di TCP, TCP Reno,
elimina la fase di partenza lenta dopo un ACK duplicato tre volte. La filosofia che ha portato a cancellare la fase di
partenza lenta in questo caso che, sebbene sia stato perso un pacchetto, l'arrivo dei tre ACK duplicati indica che
alcuni segmenti (in particolare, tre segmenti aggiuntivi oltre al segmento perso) sono stati ricevuti dal mittente.

25

Quindi, a differenza del caso di timeout, la rete mostra di essere in grado di consegnare almeno alcuni segmenti,
anche se altri si sono persi a causa della congestione. Questa eliminazione della fase di partenza lenta dopo un ACK
duplicato tre volte chiamata ripresa veloce (fast recovery).

Sono state proposte molte varianti all'algoritmo Reno. L'algoritmo TCP Vegas tenta di evitare la congestione
mantenendo comunque un buon throughput. L'idea alla base di Vegas di (1) rilevare la congestione nei router tra la
sorgente e la destinazione prima che si verifichi la perdita di pacchetti e (2) abbassare linearmente il ritmo quando
viene rilevata questa imminente perdita di pacchetti. L'imminente perdita di pacchetti viene prevista osservando i
tempi di round-trip. Maggiori sono i tempi di round-trip dei pacchetti, maggiore la congestione nei router.

EQUIT TRA LE CONNESSIONI


Consideriamo K connessioni TCP, ciascuna con un diverso percorso da estremo a estremo, ma tutte passanti
attraverso un link collo di bottiglia con ritmo di trasmissione pari a R bit/s. Per link collo di bottiglia, intendiamo che
per ogni connessione, tutti gli altri link lungo il percorso della connessione non sono congestionati e hanno capacit
trasmissiva in abbondanza rispetto alla capacit trasmissiva del link collo di bottiglia. Supponiamo che ogni
connessione stia trasferendo un grande file e che non ci sia traffico UDP che passa attraverso il link collo di bottiglia.
Un meccanismo di controllo della congestione detto essere fair (equo) se il ritmo di trasmissione medio di ogni
connessione approssimativamente pari a R/K; cio, ogni connessione ottiene un'uguale porzione della banda del
link.

Il controllo della congestione di TCP converge verso una suddivisione equa della banda di un link collo di bottiglia tra
connessioni TCP in competizione.

26

Consideriamo il caso semplice di due connessioni TCP che condividono un singolo link con velocit di trasmissione R.
Supponiamo che le due connessioni abbiano gli stessi MSS e RTT (cos che se esse hanno la stessa dimensione della
finestra di congestione, avranno lo stesso throughput), che abbiano entrambe una grande quantit di dati da spedire,
e che nessun'altra connessione TCP o datagram UDP attraversino il link condiviso. Assumiamo che le connessioni TCP
operino in modalit congestion avoidance AIMD per tutto il tempo. Se le due connessioni TCP condividono equamente
la larghezza di banda del link, allora la somma dei due throughput sarebbe uguale a R.
Non desiderabile che entrambe le connessioni ricevano una
pari frazione della capacit del link. Cos l'obiettivo dovrebbe
essere il raggiungimento di throughput che cadano da qualche
parte vicino all'intersezione fra le linee "pari suddivisione della
larghezza di banda" e "completa utilizzazione della larghezza di
banda" (vedi figura). Poich l'ammontare della larghezza di
banda utilizzata insieme dalle due connessioni inferiore a R,
non ci saranno perdite, ed entrambe le connessioni
aumenteranno la loro finestra di l per RTT. Quindi, l'insieme
dei throughput delle due connessioni segue una linea a 45
gradi (incremento uguale per le due connessioni). Alla fine, la
larghezza di banda utilizzata insieme dalle due connessioni
superer R e potrebbe intervenire la perdita di pacchetti. Le
connessioni allora diminuiscono la loro finestra di un fattore
due. Poich la larghezza di banda complessivamente utilizzata
inferiore a R, le due connessioni accrescono di nuovo i loro
throughput lungo una retta a 45 gradi. Infine, ci sar ancora una perdita e le due connessioni diminuiscono di nuovo le
dimensioni della loro finestra di un fattore due, e cos via. la larghezza di banda realizzata dalle due connessioni alla
fine fluttuer lungo la linea di pari suddivisione della larghezza di banda.

27