# Controllo di flusso

In telecomunicazioni nell'ambito delle reti di telecomunicazioni il controllo di flusso, oltre al controllo della congestione, è un tipo di controllo di trasmissione effettuato dagli agenti di una comunicazione (il mittente e il destinatario) sui pacchetti inviati e ricevuti attraverso alcuni protocolli di comunicazione come ad esempio TCP.
L'obiettivo di tale controllo è evitare che il mittente invii una quantità eccessiva di dati che potrebbero, in alcune situazioni, mandare in overflow il buffer di ricezione del destinatario generando una perdita di pacchetti e la necessità di ritrasmissione con perdita in efficienza (goodput) a causa delle ritrasmissioni dei pacchetti persi, risultando dunque particolarmente utile per il mantenimento delle prestazioni della connessione.
In altre parole il controllo di flusso è a livello logico e fisico agli estremi della connessione dipendendo esclusivamente dalle capacità riceventi del ricevitore, mentre il controllo di congestione, pur coinvolgendo anch'esso il trasmettitore e il ricevitore agli estremi, dipende dal traffico sui nodi interni di commutazione della rete di trasporto sul quale transitano anche i flussi dati di altre connessioni tra altri utenti, che sommati tra loro potrebbero appunto generare effetti di congestione interni.

## Descrizione

In uno scenario comune di connessione TCP si ha tipicamente un host mittente $A$ e un host ricevente $B$, entrambi questi host impostano dei buffer di ricezione. Il processo applicativo associato leggerà i dati da questo buffer, ma non necessariamente nel momento in cui arrivano, magari perché è impegnato in un altro compito leggendo dunque i dati in un tempo successivo generando un accodamento dei pacchetti nel buffer col rischio di overflow e conseguente perdita di pacchetti. Inoltre se l'applicazione è lenta nella lettura dei dati può accadere che il mittente mandi in overflow il buffer di ricezione inviando i dati troppo rapidamente. Il TCP offre un servizio di controllo di flusso per evitare questi inconvenienti.

### Implementazione

Il TCP offre il controllo di flusso facendo mantenere al mittente una variabile chiamata finestra di ricezione (in inglese receive window) che fornisce al mittente un'indicazione sullo spazio libero disponibile nel buffer del destinatario. Dato che il TCP è un protocollo full-duplex i due mittenti mantengono finestre di ricezione distinte.
Definiamo ora delle variabili:
* $LastByteRead$: Numero dell'ultimo byte nel flusso di dati letto dal processo applicativo in $B$.
* $LastByteRcvd$: Numero dell'ultimo byte copiato nel buffer di ricezione di $B$.
Dato che ogni segmento TCP non deve fuoriuscire dal buffer allocato si deve avere:
$LastByteRcvd-LastByteRead\leq RcvBuffer$
La finestra di ricezione, chiamata $RcvWindow$, è posta uguale alla quantità di spazio disponibile nel buffer: $RcvWindow=RcvBuffer-(LastByteRcvd-LastByteRead)$
Dato che lo spazio disponibile nel buffer varia con il tempo in funzione dei pacchetti in arrivo e all'attività di lettura del buffer stesso la dimensione di RcvWindow è anch'essa dinamica.
Quindi l'host $B$ comunica ad $A$ quanto spazio ha a disposizione nel proprio buffer posizionando il valore corrente di RcvWindow nel campo finestra di ricezione dei segmenti che manda ad $A$. A sua volta l'host $A$ mantiene due variabili che sono LastByteSent e LastByteAcked (ultimo byte inviato, ultimo byte riscontrato). La differenza tra questi due valori indica la quantità di dati inviati e non ancora riscontrati da $A$ nella connessione. Mantenendo quindi la differenza $LastByteSent-LastByteAcked\leq RcvWindow$ si garantisce che l'host $A$ non mandi in overflow il buffer di ricezione dell'host $B$. Può capitare, però, che il buffer di $B$ si riempia e, come conseguenza, l'host $A$ rimanga bloccato e non possa trasmettere ulteriori dati. Per risolvere tale problema, il TCP fa sì che l'host $A$ continui a inviare segmenti costituiti da un byte di soli zero quando la finestra di ricezione di $B$ è zero. Questi segmenti verranno scartati fino a quando il buffer di B non inizi a svuotarsi. Una volta svuotato il buffer, l'host $A$ riceverà dei riscontri non nulli della RcvWindow di $B$ e da lì continuerà ad inviare (se ci sono ancora) dati all'host $B$.