# TCP

`TCP`, acronimo di *Transmission Control Protocol*, è un protocollo del livello 4 (transport layer) che si distingue per il suo approccio connection-oriented, a differenza di UDP. Questo significa che TCP stabilisce una connessione affidabile tra i processi degli host prima di iniziare lo scambio di informazioni, garantendo così una trasmissione sicura e ordinata.

## Caratteristiche principali

- **Connection-Oriented**: prima dell'invio dei dati, TCP stabilisce una connessione tra le due estremità attraverso il meccanismo del `three-way handshake` (`SYN`, `SYN-ACK`, `ACK`). La chiusura della connessione avviene in modo simile, utilizzando un meccanismo che assomiglia a un three-way handshake (`FIN`, `FIN-ACK`, `ACK`)

- **Affidabilità**: TCP è progettato per ambienti in cui è fondamentale non perdere informazioni. TCP effettua la *rilevazione degli errori* mediante il controllo del checksum, in modo analogo a UDP. Inoltre, garantisce il corretto ordinamento dei segmenti, poiché questi potrebbero pervenire in ordine diverso da quello in cui sono stati inviati. Infine, TCP scarta i pacchetti duplicati, assicurando la precisione e l'integrità dei dati trasmessi

- **Full Duplex**: la comunicazione è bidirezionale, ovvero i dati possono essere inviati e ricevuti simultaneamente su entrambi i lati della connessione.

- **Controllo del flusso e della congestione**: TCP regola la velocità di invio dei dati in base alla capacità del ricevente, evitando di sovraccaricarlo. Questa gestione avviene attraverso meccanismi di controllo delle finestre di trasmissione e ricezione. Inoltre, TCP adotta algoritmi per il controllo della congestione, riducendo la velocità di trasmissione in caso di congestione della rete

## Segmento TCP

L'header del segmento TCP può variare da 20 byte (minimo) a 60 byte (massimo), e incapsula il payload, ovvero il messaggio generato dall'application layer.

![tcp](asset/img/tcp.png)

I campi principali dell'header TCP sono i seguenti:

- **Porta Sorgente** (16 bit o 2 byte)
- **Porta Destinazione** (16 bit o 2 byte)
- **Sequence Number** (`SEQ`) (32 bit o 4 byte): rappresenta il numero del primo byte del segmento TCP trasmesso
- **Acknowledgment Number** (`ACK`) (32 bit o 4 byte): utilizzato dal destinatario per confermare la ricezione di `n` byte. Se il mittente invia `n` byte di dati, il destinatario risponderà con un un segmento con il campo ACK impostato a `n+1`. Questo valore indica che sono stati ricevuti correttamente `n` byte e che il prossimo byte atteso ha un numero di sequenza con un valore di `n+1`. Il punto di partenza del Sequence Number non è obbligatoriamente 0, ma dipende dall'`ISN` (*Initial Sequence Number*), che viene scelto casualmente tra 0 e 2^32-1
- **Flags** (6 bit): Ogni bit rappresenta un flag con una funzione specifica.
  - `URG` (Urgent): indica che il campo `Urgent Data Pointer` contiene informazioni importanti che devono essere gestite
  - `PUSH`: il mittente richiede al destinatario di inviare immediatamente i dati all'application layer
  - `ACK`: attivato se il campo Acknowledgment Number contiene un valore valido
  - `SYN`: attivato durante l'instaurazione di una connessione
  - `FIN`: Attivato per segnalare la chiusura della connessione
  - `RST` (Reset): utilizzato per interrompere bruscamente la connessione
- `Checksum` (16 bit): controllo degli errori nel segmento TCP.
- `Options` (40 byte): Campo opzionale che può contenere informazioni aggiuntive per la gestione della connessione.
- `Receive Window` (16 bit): campo utilizzato per la gestione del flusso e delle finestre. Il destinatario indica al mittente la dimensione massima della finestra di ricezione

## Gestione del flusso

Il controllo del flusso in TCP viene realizzato tramite il meccanismo delle *finestre*, che aiuta a evitare che il mittente sovraccarichi il destinatario. In particolare:

- La `Receive Window` (finestra di ricezione) impostata dal destinatario indica quanti byte è in grado di accogliere
- Il mittente regola la quantità di dati inviati in base a questo valore (`Send Window`), garantendo che il destinatario non venga sopraffatto. La dimensione della finestra di invio può essere dinamica e viene regolata in base alla capacità di ricezione del destinatario e alle condizioni della rete.
- A livello di invio, la `congestion window` può ulteriormente limitare il flusso in base alle condizioni di rete

## Apertura della connessione TCP

Il processo di apertura di una connessione TCP prevede l'esecuzione del `three-way handshake`, che si compone di tre fasi fondamentali: `SYN`, `SYN/ACK` e `ACK`. Prima di poter trasmettere dati, entrambe le parti devono stabilire un canale di comunicazione; di solito una delle due attiva la richiesta di connessione.

La comunicazione TCP è *full-duplex*, cioè entrambi gli host possono inviare e ricevere dati simultaneamente. Ogni host gestisce indipendentemente la propria finestra di invio e quella di ricezione.

![three-way-handshake](asset/img/three-way-handshake.png)

### 1. Inizializzazione (SYN)

- **Host A**:
  - Invia un segmento TCP (chiamato `segmento SYN`) rivolto a B
  - Il segmento contiene un numero di sequenza iniziale (`SEQ`), ad esempio 1001, che identifica il primo byte del segmento TCP trasmesso
  - Viene impostata la flag `SYN` per indicare l'intenzione di stabilire una connessione

### 2. Risposta (SYN/ACK)

- **Host B**:
  - Ricevendo il segmento `SYN` di A, decide di rispondere
  - B genera il proprio numero di sequenza iniziale `ISN`, ad esempio 2001
  - Invia a A un segmento contenente il numero di sequenza (`SEQ`) impostato ad esempio a 2001, con la flag `SYN` attiva
  - La flag `ACK` é attiva per confermare di aver ricevuto il segmento inviato da A
  - Il campo `ACK number` viene impostato al valore 2001 (*ISN di A + lunghezza dati + 1*), supponendo che il SEQ di A fosse 1001, e che il segmento TCP di A fosse di 1000 byte
  - Inoltre, B indica il valore della sua `Receive Window`, che servirà ad A per regolarsi nella trasmissione dei dati

> Dimensione payload=Y SEQ=X ACK=X+Y+1

### 3. Conferma (ACK)

- **Host A**:
  - Riceve il segmento `SYN/ACK` da B
  - In risposta, invia un segmento TCP con il numero di `SEQ` impostato al valore atteso da B (2001)
  - Flag `ACK` attiva e il relativo valore di `ACK number` adeguato, ad esempio 3001, qualora B avesse incluso 1000 byte nel suo segmento (*ISN di B + lunghezza dati + 1*)
  - Un campo `Receive Window` che indica ad B la quantità di dati che A è pronta a ricevere

## Chiusura della connessione TCP

La chiusura di una connessione TCP avviene solitamente tramite una procedura a tre passi, nota anche come `three-way handshake`, in cui vengono inviati tre tipi di segmenti:

1. `FIN`: l'host A che intende terminare la propria parte della comunicazione invia un segmento TCP all'host B con la flag FIN attiva
2. `FIN/ACK`: quando l'host B riceve il segmento FIN, risponde con un segmento contenente sia la flag ACK, per confermare la ricezione del FIN, sia la flag FIN, che indica la volontà di terminare anche il proprio lato della connessione
3. `ACK`: infine, l'host A invia un segmento TCP con la flag ACK per confermare la ricezione del segmento FIN inviato da B. A questo punto, entrambe le direzioni della trasmissione dati sono state chiuse e la connessione TCP termina

### Tipi di chiusura

- *Chiusura standard*: è il processo descritto sopra
- *Chiusura brusca*: in alcuni casi, invece di seguire la procedura standard, la connessione TCP può essere terminata in modo brusco tramite l'invio di un segmento contenente la flag `RST` (reset). Tale operazione si verifica ad esempio in presenza di errori o situazioni in cui una delle due parti deve abortire immediatamente la connessione senza completare il normale scambio FIN/ACK
- *Chiusura half-closed*: si verifica quando un host chiude il proprio lato della comunicazione, inviando un segmento FIN, mentre l'altro host mantiene aperta la connessione. Questo può verificarsi, ad esempio, quando un server è oberato e deve ancora elaborare richieste in arrivo

## Controllo degli errori e ritrasmissione

Nel protocollo TCP, un segmento può andare perso, subire alterazioni (come corruzione) oppure arrivare duplicato o fuori sequenza, rispetto al SEQ atteso dal destinatario.

Per il controllo degli errori, TCP utilizza il *checksum*: se il destinatario rileva che il checksum non corrisponde, il segmento viene scartato.

Nel caso in cui un segmento venga perso, duplicato o arrivi fuori sequenza, TCP implementa meccanismi per la ritrasmissione del segmento.

Esistono due tecniche principali di ritrasmissione:

1. Invio di `ACK duplicati`: quando un segmento arriva fuori sequenza, il destinatario continua a inviare ACK ripetuti per il numero di sequenza atteso. Questi ack informano il mittente che il segmento successivo non è stato ricevuto correttamente

2. `RTO` (*Retransmission Time Out*): all'invio del primo segmento, un timer viene avviato. Se nel periodo definito dal timeout (RTO) il mittente non riceve un ACK che confermi l’avvenuta ricezione, allora il segmento si ritiene perso e viene ritrasmesso. Il timer viene azzerato al momento della ritrasmissione e rilanciato per il nuovo segmento.

In aggiunta, TCP utilizza il meccanismo degli `ACK cumulativi`: un singolo ack può confermare la corretta ricezione di più segmenti precedenti.
