\chapter{Introduzione alla programmazione di rete}
\label{cha:network}

In questo capitolo sarà fatta un'introduzione ai concetti generali che servono
come prerequisiti per capire la programmazione di rete, non tratteremo quindi
aspetti specifici ma faremo una breve introduzione al modello più comune usato
nella programmazione di rete, per poi passare ad un esame a grandi linee dei
protocolli di rete e di come questi sono organizzati e interagiscono. 

In particolare, avendo assunto l'ottica di un'introduzione mirata alla
programmazione, ci concentreremo sul protocollo più diffuso, il TCP/IP, che è
quello che sta alla base di internet, avendo cura di sottolineare i concetti
più importanti da conoscere per la scrittura dei programmi.

\section{Il modello client-server}
\label{sec:net_cliserv}

La differenza principale fra un'applicazione di rete e un programma normale è
che quest'ultima per definizione concerne la comunicazione fra ``processi''
diversi (che in generale non girano neanche sulla stessa macchina). Questo già
prefigura un cambiamento completo rispetto all'ottica del ``programma''
monolitico all'interno del quale vengono eseguite tutte le istruzioni, e
presuppone un sistema operativo ``multitasking'' in grado di eseguire processi
diversi.

Il concetto fondamentale si basa la programmazione di rete sotto Linux (e
sotto Unix in generale) è il modello \textit{client-server} in cui un
programma di servizio, il \textit{server} riceve un connessione e risponde a
un programma di utilizzo, il \textit{client}, provvedendo a quest'ultimo un
definito insieme di servizi.

Esempi di questo modello sono il WEB, ftp, telnet, ssh e praticamente ogni
servizio che viene fornito tramite la rete, ma il modello è utilizzato in
generale anche per programmi che non fanno necessariamente uso della rete,
come il sistema a finestre.

Normalmente si dividono i server in due categorie principali, e vengono detti
\textsl{concorrenti} o \textsl{iterativi}, sulla base del loro comportamento.

Un \textsl{server iterativo} risponde alla richiesta inviando i dati e resta
occupato (non rispondendo ad ulteriori richieste) fintanto che non ha concluso
la richiesta. Una volta completata la richiesta il server diventa di nuovo
disponibile.

Un \textsl{server concorrente} al momento di trattare la richiesta crea un
processo figlio incaricato di fornire i servizi richiesti, per poi porsi in
attesa di ulteriori richieste. In questo modo più richieste possono essere
soddisfatte contemporaneamente; una volta che il processo figlio ha concluso
il suo lavoro viene terminato, mentre il server originale resta sempre attivo.



\section{I protocolli di rete}
\label{sec:net_protocols}

Parlando di reti di computer si parla in genere di un insieme molto vasto ed
eterogeneo di mezzi di comunicazione che vanno dal cavo telefonico, alla fibra
ottica, alle comunicazioni via satellite; per rendere possibile la
comunicazione attraverso un così variegato insieme di mezzi sono stati
adottati una serie di protocolli, il più famoso dei quali, quello alla base
del funzionamento di internet, è il protocollo TCP/IP.

\subsection{Il modello ISO/OSI}
\label{sec:net_iso_osi}

Una caratteristica comune dei protocolli di rete è il loro essere strutturati
in livelli sovrapposti; in questo modo un livello superiore esegue richieste
al livello sottostante e da questo riceve responsi, mentre livelli uguali su
macchine diverse conversano tramite lo stesso protocollo. Questo modello di
funzionamento è stato stato standardizzato dalla \textit{International
  Standards Organization} (ISO) che ha preparato fin dal 1984 il Modello di
Riferimento \textit{Open Systems Interconnection} (OSI), strutturato in sette
livelli, secondo quanto riportato in \ntab.

\begin{table}[htb]
  \centering
  \begin{tabular}{|l|c|c|l|} 
    \hline
    \textbf{Livello} & \multicolumn{2}{|c|}{\textbf{Nome}} & \\
    \hline
    \hline
    Livello 7&\textit{Application} &\textsl{Applicazione}& \\ 
    Livello 6&\textit{Presentation} &\textsl{Presentazione}& \\ 
    Livello 5&\textit{Session} &\textsl{Sessione}& \\ 
    Livello 4&\textit{Transport} &\textsl{Trasporto}& \\ 
    Livello 3&\textit{Network} &\textsl{Rete}&   \\ 
    Livello 2&\textit{DataLink} &\textsl{Collegamento Dati}& \\
    Livello 1&\textit{Connection} &\textsl{Connessione Fisica}& \\
    \hline
\end{tabular}
\caption{I sette livelli del protocollo ISO/OSI.}
\label{tab:net_osilayers}
\end{table}

Il modello ISO/OSI è stato sviluppato in corrispondenza alla definizione
della serie di protocolli X.25 per la commutazione di pacchetto. Ma nonostante
il lavoro dettagliato di standardizzazione il modello si è rivelato
sostanzialmente troppo complesso e poco flessibile rispetto a quello,
precedente, su cui si basa TCP/IP che è diventato uno standard de facto;
quest'ultimo viene comunemente chiamato modello DoD (\textit{Department of
  Defense}), dato che fu sviluppato dall'agenzia ARPA per il Dipartimento
della Difesa Americano.

\begin{figure}[!htbp]
  \centering
  \includegraphics[width=12cm]{img/iso_tcp_comp}
  \caption{Struttura a livelli dei protocolli OSI e TCP/IP, con la  
    relative corrispondenze e la divisione fra kernel e user space.}
  \label{fig:net_osi_tcpip_comp}
\end{figure}


\subsection{Il modello DoD (TCP/IP)}
\label{sec:net_tcpip_overview}

Così come ISO/OSI anche TCP/IP è stato strutturato in livelli (riassunti in
\ntab); un confronto fra i due è riportato in \curfig\ dove viene evidenziata
anche la corrispondenza fra i rispettivi livelli (che comunque è
approssimativa) e su come essi vanno ad inserirsi all'interno del sistema
operativo rispetto alla divisione fra user space e kernel space spiegata in
\secref{sec:intro_unix_struct}.

\begin{table}[htb]
  \centering
  \begin{tabular}{|l|c|c|l|} 
    \hline
    \textbf{Livello} & \multicolumn{2}{|c|}{\textbf{Nome}} & \textbf{Esempi} \\
    \hline
    \hline
    Livello 1&\textit{Application} &\textsl{Applicazione}& 
    Telnet, FTP, etc. \\ 
    Livello 2&\textit{Transport} &\textsl{Trasporto}& TCP, UDP \\ 
    Livello 3&\textit{Network} &\textsl{Rete}& IP, (ICMP, IGMP)  \\ 
    Livello 4&\textit{Link} &\textsl{Connessione}& 
    device driver \& scheda di interfaccia  \\
    \hline
\end{tabular}
\caption{I quattro livelli del protocollo TCP/IP.}
\label{tab:net_layers}
\end{table}

Come si può notare TCP/IP è più semplice del modello ISO/OSI e strutturato in
soli quattro livelli. Il suo nome deriva dai due principali protocolli che lo
compongono, il TCP \textit{Trasmission Control Protocol} e l'IP
\textit{Internet Protocol}. Le funzioni dei vari livelli sono le seguenti:

\begin{description}
\item \textbf{Applicazione} É relativo ai programmi di interfaccia utente, in
  genere questi vengono realizzati secondo il modello client-server (vedi
  \secref{sec:net_cliserv}.
\item \textbf{Trasporto} Fornisce la comunicazione tra le due stazioni
  terminali su cui girano gli applicativi, regola il flusso delle
  informazioni, e può fornire un trasporto affidabile, cioè con recupero
  errori. Il protocollo principale di questo livello è il TCP.
\item \textbf{Rete} Si occupa dello smistamento dei singoli pacchetti su una
  rete complessa e interconnessa, a questo stesso livello operano i protocolli
  per il reperimento delle informazioni necessarie allo smistamento, per lo
  scambio di messaggi di controllo e per il monitoraggio della rete. Il
  protocollo su cui si basa questo livello è IP (sia nella attuale versione,
  IPv4 che nella nuova IPv6).
\item \textbf{Connessione} È responsabile per l'interfacciamento al
  dispositivo elettronico che effettua la comunicazione fisica, gestendo
  l'invio e la ricezione dall'hardware dei pacchetti.
\end{description}


La comunicazione fra due stazioni avviene secondo le modalità illustrate in
\nfig, dove si è riportato il flusso dei dati reali e i protocolli usati per
lo scambio di informazione su ciascuno livello.
\begin{figure}[!htb]
  \centering
  \includegraphics[width=10cm]{img/tcp_data_flux}  
  \caption{Strutturazione del flusso dei dati nella comunicazione fra due
    applicazioni attraverso i protocolli della suite TCP/IP.}
  \label{fig:net_tcpip_data_flux}
\end{figure}

La struttura della comunicazione pertanto si può riassumere nei seguenti passi:
\begin{itemize}
\item Le singole applicazioni si scambieranno i dati secondo un loro formato
  specifico, implementando un protocollo di applicazione (esempi possono
  essere HTTP, POP, telnet, SMTP, etc).
\item Questi dati vengono inviati al livello di trasporto usando
  un'interfaccia opportuna (i \textit{socket}, che esamineremo in dettaglio in
  seguito). Qui verranno spezzati in pacchetti di dimensione opportuna e
  incapsulati nel protocollo di trasporto, aggiungendo ad ogni pacchetto le
  informazioni necessarie per la sua gestione. Questo processo viene
  svolto direttamente nel kernel ad esempio dallo stack TCP nel caso il
  protocollo di trasporto sia questo.
\item Una volta composto il pacchetto nel formato adatto al protocollo di
  trasporto usato questo sarà passato al successivo livello, quello del
  collegamento che si occupa di inserire le opportune informazioni per poter
  effettuare l'instradamento nella rete ed il recapito alla destinazione
  finale. In genere questo è il livello di IP (Internet Protocol), a cui
  vengono inseriti i numeri IP che identificano i computer su internet.
\item L'ultimo passo è il trasferimento del pacchetto al driver della
  interfaccia di trasmissione che si incarica di incapsularlo nel relativo
  protocollo di trasmissione fisica usato dall'hardware usato per la
  comunicazione (ad esempio Ethernet per una scheda di rete).
\end{itemize}


\subsection{Criteri generali del design di TCP/IP}
\label{sec:net_tcpip_design}

La filosofia architetturale di TCP/IP è semplice: costruire una rete che
possa sopportare il carico in transito, ma permettere ai singoli nodi di
scartare pacchetti se il carico è temporaneamente eccessivo, o se risultano
errati o non recapitabili.

L'incarico di rendere il recapito pacchetti affidabile non spetta allo livello
di collegamento, ma ai livelli superiori. Pertanto il protocollo IP è per sua
natura inaffidabile, in quanto non è assicurata né una percentuale di
successo né un limite sui tempi di consegna dei pacchetti.

È il livello di trasporto che si deve occupare (qualora necessiti) del
controllo del flusso dei dati e del recupero degli errori; questo è realizzato
dal protocollo TCP. La sede principale di "intelligenza" della rete è pertanto
al livello di trasporto o superiore.

Infine le singole stazioni collegate alla rete non fungono soltanto da punti
terminali di comunicazione, ma possono anche assumere il ruolo di router, per
l'interscambio di pacchetti da una rete ad un'altra. Questo rende possibile la
flessibilità della rete che è in grado di adattarsi ai mutamenti delle
interconnessioni.

La caratteristica essenziale che rende tutto ciò possibile è la strutturazione
a livelli tramite l'incapsulamento. Ogni pacchetto di dati viene incapsulato
nel formato del livello successivo, fino al livello della connessione fisica.
In questo modo il pacchetto ricevuto ad un livello $n$ dalla stazione di
destinazione è esattamente lo stesso spedito dal livello $n$ dalla sorgente.
Questo rende facile il progettare il software facendo riferimento unicamente a
quanto necessario ad un singolo livello, con la confidenza che questo poi sarà
trattato uniformemente da tutti i nodi della rete.


\section{Il protocollo TCP/IP}
\label{sec:net_tpcip}

Come appena mostrato il protocollo TCP/IP è un insieme di protocolli diversi,
che operano su 4 livelli diversi. Per gli interessi della programmazione di
rete però sono importanti principalmente i due livelli centrali, e soprattutto
quello di trasporto. 

La principale interfaccia di programmazione di rete, quella dei socket, è
infatti un'interfaccia nei confronti di quest'ultimo. Questo avviene perché al
di sopra del livello di trasporto i programmi hanno a che fare solo con
dettagli specifici delle applicazioni, mentre al di sotto vengono curati tutti
i dettagli relativi alla comunicazione. È pertanto naturale definire una API
su questo confine tanto più che è proprio li (come evidenziato in \pfig) che
nei sistemi unix (e non solo) viene inserita la divisione fra kernel space e
user space.

In realtà in un sistema unix è possibile accedere anche agli altri livelli
inferiori (e non solo a quello di trasporto) con opportune interfacce (la cosa
è indicata in \pfig\ lasciando uno spazio fra UDP e TCP), ma queste vengono
usate solo quando si vogliono fare applicazioni di sistema per il controllo
della rete a basso livello, un uso quindi molto specialistico, e che non
rientra in quanto trattato qui.

In questa sezione daremo una breve descrizione dei vari protocolli di TCP/IP,
concentrandoci per le ragioni esposte sul livello di trasporto. All'interno di
questo privilegeremo poi il protocollo TCP, per il ruolo centrale che svolge
nella maggior parte delle applicazioni.


\subsection{Il quadro generale}

Benché si parli di TCP/IP questa famiglia di protocolli è composta anche da
altri membri. In \nfig\ si è riportato uno schema che mostra un panorama sui
vari protocolli della famiglia, e delle loro relazioni reciproche e con
alcune dalle principali applicazioni che li usano.

\begin{figure}[!htbp]
  \centering
  \includegraphics[width=10cm]{img/tcpip_overview}  
  \caption{Panoramica sui vari protocolli che compongono la suite TCP/IP.}
  \label{fig:net_tcpip_overview}
\end{figure}

I vari protocolli mostrati in figura sono i seguenti:

\begin{list}{}{}
\item \textsl{IPv4} \textit{Internet Protocol version 4}. È quello che
  comunemente si chiama IP. Ha origine negli anni '80 e da allora è la base su
  cui è costruita internet. Usa indirizzi a 32 bit e provvede la trasmissione
  dei pacchetti TCP, UDP, ICMP e IGMP.
\item \textsl{IPv6} \textit{Internet Protocol version 6}. È stato progettato a
  metà degli anni '90 per rimpiazzare IPv4. Ha indirizzi a 128 bit e effettua
  lo stesso servizio di trasporto di IPv4 per i pacchetti TCP, UDP e ICPMv6.
\item \textsl{TCP} \textit{Trasmission Control Protocol}. È un protocollo
  orientato alla connessione che provvede un trasporto affidabile e
  bidirezionale di un flusso di dati. I socket TCP sono esempi di
  \textit{stream socket}. Il protocollo ha cura di tutti gli aspetti del
  trasporto, come l'acknoweledgment, i timeout, la ritrasmissione, etc. È 
  usato dalla maggior parte delle applicazioni. Può essere usato sia con IPv4
  che con IPv6.
\item \textsl{UDP} \textit{User Datagram Protocol}. È un protocollo senza
  connessione a pacchetti. I socket UDP sono esempi di \textit{datagram
    socket}. Contrariamente al TCP in protocollo non è affidabile e non c'è
  garanzia che i pacchetti raggiungano la loro destinazione, né sull'eventuale
  ordine di arrivo. Può essere usato sia con IPv4 che con IPv6.
\item \textsl{ICMP} \textit{Internet Control Message Protocol}. Gestisce gli
  errori e trasporta l'informazione di controllo fra stazioni remote e
  instradatori (\textit{host} e \textit{router}). I messaggi sono normalmente
  generati dal software del kernel che gestisce la comunicazione TCP/IP, anche
  se ICMP può venire usato direttamente da alcuni programmi come
  \texttt{ping}. A volte ci si riferisce ad esso come ICPMv4 per distinguerlo
  da ICMPv6.
\item \textsl{IGMP} \textit{Internet Group Management Protocol}. É un
  protocollo usato per il \textit{multicasting} (vedi
  \secref{sec:xxx_multicast}), che è opzionale in IPv4.
\item \textsl{ARP} \textit{Address Resolution Protocol}. È il protocollo che
  mappa un indirizzo IP in un indirizzo hardware (come un indirizzo
  internet). È usato in reti di tipo broadcast come Ethernet, Token Ring o
  FDDI ma non serve in connessioni punto-punto.
\item \textsl{RARP} \textit{Reverse Address Resolution Protocol}. È il
  protocollo che mappa un indirizzo hardware in un indirizzo IP. Viene usato a
  volte per durante il boot per assegnare un indirizzo IP ad una macchina.
\item \textsl{ICMPv6} \textit{Internet Control Message Protocol, version 6}.
  Combina per IPv6 le funzionalità di ICMPv4, IGMP e ARP.
\item \textsl{NETLINK} \textit{Netlink}.
  Provvede l'interfaccia di accesso alla comunicazione a basso livello.
\end{list}

Gran parte delle applicazioni comunicano usando TCP o UDP, ed alcune si
rifanno ad IP (ed i suoi correlati ICMP e IGMP); benché sia TCP che UDP siano
basati su IP e sia possibile intervenire a questo livello con i \textit{raw
  socket} questa tecnica è molto meno diffusa e a parte applicazioni
particolari si preferisce sempre usare i servizi messi a disposizione dai due
protocolli precedenti.  Per questo motivo a parte alcuni brevi accenni su IP
in questa sezione ci concentreremo sul livello di trasporto.

\subsection{Internet Protocol (IP)}
\label{sec:net_ip}

Quando si parla di IP ci si riferisce in genere alla versione attualmente in
uso che è la versione 4 (e viene pertanto chiamato IPv4). Questa versione
venne standardizzata nel 1981 dall'RFC~719.

Internet Protocol nasce per disaccoppiare le applicazioni della struttura
hardware delle reti di trasmissione, e creare una interfaccia di trasmissione
dei dati indipendente dal sottostante substrato di rete, che può essere
realizzato con le tecnologie più disparate (Ethernet, Token Ring, FDDI, etc.).
Il compito di IP è pertanto quello di trasmettere i pacchetti da un computer
all'altro della rete; le caratteristiche essenziali con cui questo viene
realizzato in IPv4 sono due:

\begin{itemize}
\item \textit{Universal addressing} la comunicazione avviene fra due host
  identificati univocamente con un indirizzo a 32 bit che può appartenere ad
  una sola interfaccia di rete.
\item \textit{Best effort} viene assicurato il massimo impegno nella
  trasmissione, ma non c'è nessuna garanzia per i livelli superiori né sulla
  percentuale di successo né sul tempo di consegna dei pacchetti di dati.
\end{itemize}

Negli anni '90 la crescita vertiginosa del numero di macchine connesse a
internet ha iniziato a far emergere i vari limiti di IPv4, per risolverne i
problemi si è perciò definita una nuova versione del protocollo, che (saltando
un numero) è diventata la versione 6. IPv6 nasce quindi come evoluzione di
IPv4, mantendone inalterate le funzioni che si sono dimostrate valide,
eliminando quelle inutili e aggiungendone poche altre per mantenere il
protocollo il più snello e veloce possibile.

I cambiamenti apportati sono comunque notevoli e si possono essere riassunti a
grandi linee nei seguenti punti:
\begin{itemize}
\item l'espansione delle capacità di indirizzamento e instradamento, per
  supportare una gerarchia con più livelli di indirizzamento, un numero di
  nodi indirizzabili molto maggiore e una autoconfigurazione degli indirizzi
\item l'introduzione un nuovo tipo di indirizzamento, l'\textit{anycast} che
  si aggiunge agli usuali \textit{unycast} e \textit{multicast}
\item la semplificazione del formato della testata, eliminando o rendendo
  opzionali alcuni dei campi di IPv4, per eliminare la necessità di
  riprocessamento della stessa da parte dei router e contenere l'aumento di
  dimensione dovuto all'ampliamento degli indirizzi
\item un supporto per le opzioni migliorato, per garantire una trasmissione
  più efficiente del traffico normale, limiti meno stringenti sulle dimensioni
  delle opzioni, e la flessibilità necessaria per introdurne di nuove in
  futuro
\item il supporto per delle capacità di qualità di servizio (QoS) che
  permettano di identificare gruppi di dati per i quali si può provvedere un
  trattamento speciale (in vista dell'uso di internet per applicazioni
  multimediali e/o ``real-time'')
\end{itemize}

Maggiori dettagli riguardo a caratteristiche, notazioni e funzionamento del
protocollo IP sono forniti nell'appendice \capref{cha:ip_protocol}.

 
\subsection{UDP: User Datagram Protocol)}
\label{sec:net_udp}

UDP è un protocollo di trasporto molto semplice, la sua descrizione completa è
contenuta dell'RFC~768, ma in sostanza esso è una semplice interfaccia a IP
dal livello di trasporto. Quando un'applicazione usa UDP essa scrive un
pacchetto di dati (il cosiddetto \textit{datagram} che da il nome al
protocollo) su un socket, al pacchetto viene aggiunto un header molto semplice
(per una descrizione più accurata vedi \secref{sec:xxx_udp}), e poi viene
passato al livello superiore (IPv4 o IPv6 che sia) che lo spedisce verso la
destinazione.  Dato che né IPv4 né IPv6 garantiscono l'affidabilità niente
assicura che il pacchetto arrivi a destinazione, né che più pacchetti arrivino
nello stesso ordine in cui sono stati spediti.

Pertanto il problema principale che si affronta quando si usa UDP è la
mancanza di affidabilità, se si vuole essere sicuri che i pacchetti arrivino a
destinazione occorrerà provvedere con l'applicazione all'interno della quale
si dovrà inserire tutto quanto necessario a gestire la notifica di
ricevimento, la ritrasmissione, il timeout. 

Si tenga conto poi che in UDP niente garantisce che i pacchetti arrivino nello
stesso ordine in cui sono stati trasmessi, e può anche accadere che i
pacchetti vengano duplicati nella trasmissione, e non solo perduti. Di tutto
questo di nuovo deve tenere conto l'applicazione.

Un'altro aspetto di UDP è che se un pacchetto raggiunge correttamente la
destinazione esso viene passato all'applicazione ricevente in tutta la sua
lunghezza, la trasmissione avviene perciò per \textit{record} la cui lunghezza
viene anche essa trasmessa all'applicazione all'atto del ricevimento.

Infine UDP è un protocollo che opera senza connessione
(\textit{connectionless}) in quanto non è necessario stabilire nessun tipo di
relazione tra origine e destinazione dei pacchetti. Si hanno così situazioni
in cui un client può scrivere su uno stesso socket pacchetti destinati a
server diversi, o un server ricevere su un socket pacchetti provenienti da
client diversi.  Il modo più semplice di immaginarsi il funzionamento di UDP è
quello della radio, in cui si può ``trasmettere a'' e ``ricevere da'' più
stazioni usando la stessa frequenza.

Nonostante gli evidenti svantaggi comportati dall'inaffidabilità UDP ha il
grande pregio della velocità che in certi casi è essenziale; inoltre si presta
bene per le applicazioni in cui la connessione non è necessaria e
costituirebbe solo un peso di prestazioni mentre una perdita di pacchetti può
essere tollerata, ad esempio quelle che usano il multicasting.

\subsection{TCP: Transport Control Protocol)}
\label{sec:net_tcp}

Il TCP è un protocollo molto complesso, definito nell'RFC~739 e completamente
diverso da UDP; alla base del suo design infatti non stanno semplicità e
velocità, ma la ricerca della massima affidabilità possibile nella
trasmissione dei dati.

La prima differenza con UDP è che TCP provvede sempre una connessione diretta
fra un client e un server, attraverso la quale essi possono comunicare; per
questo il paragone più appropriato per questo protocollo è quello del
collegamento telefonico, in quanto prima viene stabilita una connessione fra
due i due capi della comunicazione su cui poi viene quest'ultima viene
effettuata.

Caratteristica fondamentale di TCP è l'affidabilità; quando i dati vengono
inviati attraverso una connessione ne viene richiesto un ``ricevuto''
(il cosiddetto \textit{acknowlegment}), se questo non arriva essi verranno
ritrasmessi per un determinato numero di tentativi, intervallati da un
periodo di tempo crescente, fino a che sarà considerata fallita o caduta la
connessione (e generato un errore di \textit{time-out}), dopo un periodo di
tempo che dipende dall'implementazione e che può variare far i
quattro e i dieci minuti.

Inoltre per tenere conto delle diverse condizioni in cui può trovarsi la linea
di comunicazione TCP comprende anche un algoritmo di calcolo dinamico del
tempo di andata e ritorno dei pacchetti (il cosiddetto RTT, 
\textit{round-trip time}) fra un client e un server che lo rende in grado di
adattarsi alle condizioni della rete per non generare inutili ritrasmissioni o
cadere facilmente in timeout.

Inoltre TCP è in grado di preservare l'ordine dei dati assegnando un numero di
sequenza ad ogni byte che trasmette. Ad esempio se un'applicazione scrive 3000
byte su un socket TCP, questi potranno essere spezzati dal protocollo in due
segmenti (le unità di dati passate da TCP a IP vengono chiamate
\textit{segment}) di 1500 byte, di cui il primo conterrà il numero di
sequenza $1-1500$ e il secondo il numero $1501-3000$. In questo modo anche se
i segmenti arrivano a destinazione in un ordine diverso, o se alcuni arrivano
più volte a causa di ritrasmissioni dovute alla perdita dei ricevuto,
all'arrivo sarà comunque possibile riordinare i dati e scartare i duplicati.

Il protocollo provvede anche un controllo di flusso (\textit{flow control}),
cioè specifica sempre all'altro capo della trasmissione quanti dati può
ricevere tramite una \textit{advertised window} (letteralmente finestra
annunciata), che indica lo spazio disponibile nel buffer di ricezione,
cosicché nella trasmissione non vengano inviati più dati di quelli che possono
essere ricevuti. 

Questa finestra cambia dinamicamente diminuendo con la ricezione dei dati dal
socket ed aumentando con la lettura di quest'ultimo da parte
dell'applicazione, se diventa nulla il buffer di ricezione è pieno e non
verranno accettati altri dati.  Si noti che UDP non provvede niente di tutto
ciò per cui nulla impedisce che vengano trasmessi pacchetti ad un rate che il
ricevitore non può sostenere.

Infine attraverso TCP la trasmissione è sempre bidirezionale (in inglese
\textit{full-duplex}), è cioè possibile sia trasmettere che ricevere allo
stesso tempo, il che poi comporta che quanto dicevamo a proposito del
controllo di flusso e della gestione della sequenzialità dei dati viene
effettuato per entrambe le direzioni di comunicazione.

Una descrizione più accurata del protocollo è fornita in appendice
\capref{cha:tcp_protocol}.

\subsection{Limiti e dimensioni riguardanti la trasmissione dei dati}
\label{sec:net_lim_dim}

Un aspetto di cui bisogna tenere conto, e che ritornerà in seguito, è che ci
sono una serie di limiti a cui la trasmissione dei dati attraverso i vari
livelli del protocollo deve sottostare, limiti che è opportuno tenere presente
perché in certi casi si possono avere delle conseguenze sul comportamento
delle applicazioni.

Un elenco di questi limiti è il seguente, insieme ad un breve accenno alle
loro origini ed alle eventuali implicazioni che possono avere:
\begin{itemize}
\item La dimensione massima di un pacchetti IP è di 65535 byte, compreso
  l'header. Questo è dovuto al fatto che la dimensione è indicata da un campo
  apposito nell'header di IP che è lungo 16 bit (vedi
  \tabref{tab:IP_ipv4head}).
\item La dimensione massima di un pacchetto normale di IPv6 è di 65575 byte,
  il campo apposito nell'header infatti è sempre a 16 bit, ma la dimensione
  dell'header è fissa e di 40 byte e non è compresa nel valore indicato dal
  suddetto campo. Inoltre IPv6 ha la possibilità di estendere la dimensione di
  un pacchetto usando la \textit{jumbo payload option}.
\item Molte reti fisiche hanno un MTU (\textit{maximum transfer unit}) che
  dipende dal protocollo specifico usato al livello di link. Il più comune è
  quello dell'Ethernet che è pari a 1500 byte, una serie di valori possibili
  sono riportati in \ntab.
\end{itemize}

Quando un pacchetto IP viene inviato su una interfaccia di rete e le sue
dimensioni eccedono la MTU viene eseguita la cosiddetta
\textit{frammentazione}, i pacchetti cioè vengono spezzati (sia da IPv4 che da
IPv6, anche se i pacchetti frammentati sono gestiti con modalità
diverse\footnote{il primo usa un flag nell'header, il secondo una opportuna
  opzione, si veda \secref{cha:ip_protocol}}), in blocchi più piccoli che
possono essere trasmessi attraverso l'interfaccia.

\begin{table}[!htb]
  \centering
  \begin{tabular}[c]{|l|c|}
    \hline
    \textbf{Rete} & \textbf{MTU} \\
    \hline
    \hline
    Hyperlink & 65535 \\
    Token Ring IBM (16 Mbit/sec) & 17914 \\
    Token Ring IEEE 802.5 (4 Mbit/sec) & 4464 \\
    FDDI & 4532 \\
    Ethernet & 1500 \\
    X.25 & 576 \\
    \hline
  \end{tabular}
  \caption{Valori della MTU (\textit{maximum transfer unit}) per una serie di
    reti diverse.}
  \label{tab:net_mtu_values}
\end{table}

La MTU più piccola fra due stazioni viene in genere chiamata \textit{path
  MTU}, che dice qual'è la lunghezza massima oltre la quale un pacchetto
inviato da una stazione ad un'altra verrebbe senz'altro frammentato. Si tenga
conto che non è affatto detto che la \textit{path MTU} sia la stessa in
entrambe le direzioni, perché l'instradamento può essere diverso nei due
sensi, con diverse tipologie di rete coinvolte.

Una delle differenze fra IPv4 e IPv6 é che per IPv6 la frammentazione può
essere eseguita solo alla sorgente, questo vuol dire che i router IPv6 non
frammentano i pacchetti che trasmettono (anche se possono frammentare i
pacchetti che generano loro stessi), mentre i router IPv4 si. In ogni caso una
volta frammentati i pacchetti possono essere riassemblati solo alla
destinazione.

Nell'header di IPv4 è previsto il flag \texttt{DF} che specifica che il
pacchetto non deve essere frammentato; un router che riceva un pacchetto le
cui dimensioni eccedano quelle dell'MTU della rete di destinazione genererà un
messaggio di errore ICMPv4 di tipo \textit{destination unreachable,
  fragmentation needed but DF bit set}.

Dato che i router IPv6 non possono effettuare la frammentazione la ricezione
di un pacchetto di dimensione eccessiva per la ritrasmissione genererà sempre
un messaggio di errore ICMPv6 di tipo \textit{packet too big}.

Dato che il meccanismo di frammentazione e riassemblaggio comporta
inefficienza normalmente viene utilizzato il procedimento della \textit{path
  MTU discover} (vedi RFC~1191 per IPv4 e RFC~1981 per IPv6) che permette di
trovare il \textit{path MTU} fra due stazioni; per la realizzazione del
procedimento si usa il flag DF di IPv4 e il comportamento normale di IPv6
inviando delle opportune serie di pacchetti (per i dettagli vedere l'RFC~1191
per IPv4 e l'RFC~1981 per IPv6) fintanto che non si hanno più errori. 

Il TCP usa sempre questo meccanismo, che per le implementazioni di IPv4 è
opzionale, mentre diventa obbligatorio per IPv6.  Per IPv6 infatti, non
potendo i router frammentare i pacchetti, è necessario, per poter comunicare,
conoscere il \textit{path MTU}.


Infine TCP definisce una \textit{maximum segment size} MSS che annuncia
all'altro capo la dimensione massima del segmento di dati.


%\subsection{Il passaggio dei dati in TCP}
%\label{sec:net_tcp_pass}

%\subsection{Il passaggio dei dati in UDP}
%\label{sec:net_udp_pass}
