Affidabilità della comunicazione

Affidabilità della comunicazione

Vediamo di seguito di illustrare le caratteristiche, e le problematiche, inerenti l’affidabilità della connessione TCP.

Consegna ordinata ed eliminazione di duplicati

Come sappiamo il Sequence Number, o numero di sequenza, serve ad identificare in maniera corretta e ordinata l’esatta sequenza del flusso dato di un segmento TCP. Con la trasmissione a commutazione di pacchetto della rete dati infatti ogni pacchetto del messaggio, a seconda del traffico di rete, può seguire percorsi molto diverse per giungere a destinazione, dove può quindi giungere fuori sequenza: è quindi necessario prevedere un meccanismo che consenta di ricostruire fedelmente la corretta sequenza dei pacchetti in modo da garantire l’integrità e correttezza del messaggio ricostruito dal destinatario.

In modalità ricezione il TCP si aspetta di ricevere i segmenti nel corretto ordine, e adotta le seguenti procedure:

Se il numero di sequenza ricevuto è quello effettivamente atteso, allora il protocollo provvederà ad inviare direttamente il carico utile del segmento (ovvero il suo campo Dati) al processo di livello applicativo che ne ha fatto richiesta e libera i propri buffer, in attesa di altri pacchetti.

Se il numero di sequenza ricevuto è maggiore di quello atteso allora il protocollo deduce che uno o più segmenti ad esso precedenti sono andati persi, oppure che sono in ritardo e si trovano ancora al livello Network sottostante, o che sono ancora in transito sulla rete. In questo caso il protocollo memorizza in un buffer temporaneo il campo “Dati” del segmento ricevuto fuori sequenza e, prima di consegnarlo al processo applicativo che ne ha fatto richiesta, attende di aver ricevuto e consegnato anche tutti i segmenti precedenti non ancora pervenuti, e passanti anch’essi per il buffer. Il protocollo resta in attesa dei segmenti mancanti fino ad un tempo limite prefissato (time-out), dopo di che i pacchetti vengono contrassegnati come scaduti. Non appena i segmenti attesi vengono ricevuti, il buffer viene liberato, e si rende utilizzabile per altre comunicazioni. Dal punto di vista del processo applicativo, quindi, questo processo è del tutto trasparente: l’applicazione riceverà i dati nell’ordine corretto anche se la rete, per qualsiasi motivo, ha alterato il corretto ordine di sequenza. In questo modo il protocollo TCP realizza il requisito della consegna ordinata dei dati.

Se il numero di sequenza ricevuto è inferiore a quello atteso, il segmento viene considerato un duplicato di uno già ricevuto e già inviato allo strato applicativo soprastante e dunque viene scartato. Questo meccanismo permette di realizzare l’eliminazione dei duplicati di rete.

Riscontro dei pacchetti e ritrasmissione

Per ogni segmento dati ricevuto in sequenza in una trasmissione tramite protocollo TCP, l’host ricevente provvede ad inviare un segnale, ovvero un Acknowledgment Number (numero di riscontro) a conferma dell’avvenuta ricezione del messaggio.

Per ogni segmento ricevuto in sequenza, inoltre, TCP lato ricevente invia un Acknowledgment Number o numero di riscontro dell’avvenuta ricezione. In particolare, il numero di Ack inviato da A a B è pari al numero di sequenza atteso da A e quindi riguarda il flusso dati che va da B ad A: si tratta quindi di un vero e proprio report di quanto ricevuto.

In questo ambito il protocollo TCP adotta la politica di conferma cumulativa, ovvero l’arrivo del numero di Ack indica all’host trasmittente che l’host ricevente ha correttamente ricevuto, ed inoltrato al proprio processo applicativo, il segmento avente numero di sequenza pari al numero di Ack – 1 e quindi anche tutti i segmenti precedenti. Per questo motivo vengono mantenuti in un buffer temporaneo tutti i dati inviati, ma per i quali non si è ancora registrato il riscontro da parte del ricevente: infatti quando l’host mittente riceve dall’host ricevente il numero di riscontro per un certo segmento, ne deduce che tutti quelli precedenti sono stati correttamente ricevuti, e quindi provvede a liberare il proprio buffer.

La permanenza nel buffer, come abbiamo visto, è limitata nel tempo, allo scopo ovviamente di evitare tempi di giacenze troppo lunghi per la trasmissione. All’invio di un segmento, l’host mittente avvia un timer, il cosiddetto timer di ritrasmissione o RTO (Retransmission Time Out): se non verrà ricevuto l’ack di ricezione dal destinatario entro un lasso di tempo determinato, il mittente ne deduce che i segmenti inviati siano andati persi, e provvede a trasmetterli nuovamente.

Notiamo che nel protocollo TCP il meccanismo degli Acknowledge Number non consente all’host destinatario di comunicare all’host mittente che un determinato segmento è andato perso, ma solo che alcune dei segmenti successivi sono stati ricevuti, quindi è possibile che per un solo pacchetto perso ne debbano essere ritrasmessi molti. Questa tecnica si chiama Go-Back-N, ovvero vai indietro di N segmenti. La strategia alternativa si chiama Selective Repeat, e prevede che solo i pacchetti effettivamente persi vengano inviati di nuovo, e presuppone l’utilizzo di ulteriori campi.

Questo comportamento, non ottimale, è tuttavia ampiamente compensato dalla semplicità della gestione del protocollo.

Il meccanismo dei numeri di Ack e i relativi timer di ritrasmissione permette quindi di realizzare una consegna affidabile con controllo degli errori, ovvero permette di garantire che tutti i dati inviati siano comunque consegnati nel caso in cui qualche pacchetto possa essere andato perso nel transito attraverso la rete.

Controllo di flusso

Un altro sistema che garantisce la correttezza e l’affidabilità delle comunicazioni TCP è il cosiddetto sistema di controllo di flusso, ovvero un meccanismo che si occupa di controllare che il flusso dati in trasmissione non super le capacità di ricezione o di memorizzazione dell’host ricevente, con la relativa possibile perdita e aumento della latenza della comunicazione dovuta alla necessità di attivare il processo di ritrasmissione. Tale meccanismo viene implementato attraverso la specifica, da parte dell’host di destinazione, di un apposti campo chiamato RCV_WND, ovvero Receive Window (finestra di ricezione). Si tratta di un valore che dipende dallo spazio disponibile e indica il massimo numero di segmenti ricevibili dal destinatario.

Problemi nel controllo di flusso in TCP

Il sistema di controllo del flusso presenta tuttavia alcuni problemi, che si possono verificare sia nell’host di trasmissione che in quello di ricezione. Tali problemi sono noti con il termine di Silly Windows Syndrome, letteralmente “Sindrome da finestra sciocca”, e sono dovuti essenzialmente a causa delle differenti velocità di lettura/scrittura dei buffer utilizzati per memorizzare temporaneamente i pacchetti in attesa delle corrette sequenziazione.

Il Silly Windows si verifica da lato dell’host ricevitore quando questo svuota molto lentamente il proprio buffer di ricezione. Quando il buffer di ricezione è pieno, sarà necessario aspettare la sua liberazione prima di poter ricevere nuovi pacchetti dal mittente. Quando si libera un po’ di spazio, ovvero si ottiene una Recive Window, seppur piccola, tale valore viene comunicato indietro all’host mittente.

Tuttavia, la dimensione potenzialmente ridotta della finestra di ricezione può causare problemi anche all’host di trasmissione, che potrebbe essere costretto ad inviare segmenti molto corti rispetto alla dimensione canonica di 20 byte, con conseguente riduzione dell’efficienza della trasmissione.

Per ovviare a questo problema è opportuno che, prima di riprendere la trasmissione, il destinatario abbia il proprio buffer svuotato per metà, per lo meno di una quantità pari al Maximum Segment Size, e non svuotato magari solo in piccola parte. Il destinatario, quindi, comunica un dato falso al mittente, inviando dimensione del proprio buffer uguale a 0, e causando così l’interruzione dell’invio di pacchetti da parte del mittente. Questo sistema viene gestito dall’algoritmo di Clark.

Il problema della Silly Windows dal lato dell’host trasmettitore si verifica quando l’applicazione genera i dati da inviare molto lentamente. Dal momento che il protocollo TCP legge i dati presenti nel buffer di trasmissione e crea dei segmenti che invia a destinazione, nel caso in cui l’applicazione mittente generi tali dati molto lentamente, si potrebbe verificare l’evenienza che l’entità TCP potrebbe essere forzata a creare segmenti molto corti e con tanto overhead. Questo problema viene risolto facendo in modo che la sorgente TCP provveda intanto ad inviare la prima porzione di dati, anche se corta, ma che i successivi segmenti vengano creati solo dopo che il buffer d’uscita si sia riempito con una quantità di dati sufficiente a riempire almeno un segmento di dimensioni Maximum Segment Size, oppure quando l’host mittente riceve un riscontro valido, ovvero un Ack. Questo meccanismo viene gestito dall’algoritmo di Nagle.

Controllo di congestione

Un altro sistema di controllo effettuato a livello TCP per garantire l’affidabilità della comunicazione è il controllo di congestione. Tale sistema è mirato a prevenire quanto più possibile i fenomeni di congestione del traffico di rete dovuto all’eccessiva quantità di pacchetti in circolazione, con relativa possibile perdita di dati e maggiore latenza della trasmissione. Il meccanismo funziona essenzialmente occupandosi di effettuare una modulazione temporale sulla quantità opportuna di dati da tenere in circolazione, in funzione dello stato interno di congestione della rete. La particolarità di questo sistema di controllo sta nel fatto che esso viene effettuato agendo sulla trasmissione agli estremi del canale di comunicazione, ovvero sui terminali di rete e non attraverso la commutazione inter alla rete, grazie alle informazioni reperite sui terminali stessi circa lo stato di trasmissione dei pacchetti.

Gli host di invio e destinazione si occupano quindi di stimare il livello di congestione della rete avendo come riferimento il numero di pacchetti persi: tale numero viene desunto dal numero di mancati Ack che il destinatario torna indietro al mittente. Questo parametro viene memorizzato in un apposito campo, chiamato C_WND, ovvero Congestion Window (Finestra di Congestione), la quale assegna dinamicamente nel tempo il numero massimo di segmenti da trasmettere al destinatario.