Aggiustate le referenze e data una rilettura con qualche correzione.
[gapil.git] / elemtcp.tex
index 7929fcca6c6e400e0606c5e75a0f1cfc0f7728db..3f256c875ef8838d0e1ecf9957e3f72b8c5fd71c 100644 (file)
@@ -7,40 +7,40 @@ nei due esempi elementari forniti in precedenza (vedi \ref{sec:net_cli_sample}
 e \ref{sec:net_serv_sample}), previa una descrizione delle principali
 caratteristiche del funzionamento di una connessione TCP.
 
-La seconda parte del capitolo sarà poi dedicata ad una riscrittura
-dell'esempio precedente per trasformarlo in una prima applicazione
-client/server semplice, ma completa, che implementi il servizio standard
-\texttt{time} su TCP (vedremo in seguito un esempio anche con UDP).
-
+La seconda parte del capitolo sarà poi dedicata alla scrittura di una prima
+semplice applicazione client/server completa, che implementi il servizio
+standard \texttt{echo} su TCP.
 
 \section{Il funzionamento di una connessione TCP}
 \label{sec:TCPel_connession}
 
-Prima di entrare nei dettagli di come si usano le varie funzioni dei socket
-che operano con TCP, è fondamentale capire alcune basi del funzionamento del
-protocollo, ed in particolare su come si stabilisce una connessione, come la
-si conclude e qual'è il significato dei vari stati del protocollo ad essa
-connessi.
+Prima di entrare nei dettagli delle funzioni usate nelle applicazioni che
+utilizzano i socket TCP, è fondamentale spiegare alcune basi del funzionamento
+del TCP, la conoscenza del funzionamento del protocollo è infatti essenziale
+per capire il modello di programmazione ed il funzionamento delle API.
 
-La conoscenza del funzionamento del protocollo è infatti essenziale per capire
-il modello di programmazione ed il funzionamento delle API. In tutto questo è
-di grande aiuto il programma \texttt{netstat}, che useremo per mostrare lo
-stato in cui si trova ciascuna connessione attiva.
+In particolare ci concentreremo sulle modalità con le quali il protocollo da
+inizio e conclude una connessione; faremo anche un breve accenno al
+significato di alcuni dei vari stati che il protocollo assume durante la vita
+di una connessione, che possono essere osservati per ciascun socket attivo con
+l'uso del programma \texttt{netstat}.
 
 \subsection{La creazione della connessione: il \textit{three way handushake}}
 \label{sec:TCPel_conn_cre}
 
-Lo scenario tipico che si verifica quando si deve stabilire una connessione
-TCP (lo stesso usato negli esempi elementari \ref{fig:net_cli_code} e
-\ref{fig:net_serv_code}) la successione degli eventi è la
-seguente:
-
+Il processo che porta a creare una connessione TCP è chiamato \textit{three
+  way handushake}; la successione tipica degli eventi (la stessa che si
+verifica utilizzando il codice dei due precedenti esempi elementari
+\ref{fig:net_cli_code} e \ref{fig:net_serv_code}) che porta alla creazione di
+una connessione è la seguente:
 \begin{itemize}
 \item Il server deve essere preparato per accettare le connessioni in arrivo;
-  il procedimento si chiama \textsl{apertura passiva} del socket (da
+  il procedimento si chiama \textsl{apertura passiva} del socket (in inglese
   \textit{passive open}); questo viene fatto chiamando la sequenza di funzioni
-  \texttt{socket}, \texttt{bind} e \texttt{listen}. Infine il server chiama la
-  funzione \texttt{accept} e il processo si blocca in attesa di connessioni.
+  \texttt{socket}, \texttt{bind} e \texttt{listen}. Completata l'apertura
+  passiva il server chiama la funzione \texttt{accept} e il processo si blocca
+  in attesa di connessioni.
   
 \item Il client richiede l'inizio della connessione usando la funzione
   \texttt{connect}, attraverso un procedimento che viene chiamato
@@ -57,11 +57,11 @@ seguente:
     funzioni particolari del protocollo e danno il nome al segmento, (per
     maggiori dettagli vedere \ref{cha:tcp_protocol})}, in sostanza viene
   inviato al server un pacchetto IP che contiene solo gli header IP e TCP (con
-  un numero di sequenza) e le opzioni di TCP.
+  il numero di sequenza iniziale e il flag \texttt{SYN}) e le opzioni di TCP.
   
 \item il server deve dare ricevuto (l'\textit{acknowledge}) del \texttt{SYN}
   del client, inoltre anche il server deve inviare il suo \texttt{SYN} al
-  client (e trasmettere il numero di sequenza iniziale) questo viene fatto
+  client (e trasmettere il suo numero di sequenza iniziale) questo viene fatto
   ritrasmettendo un singolo segmento in cui entrambi i flag \texttt{SYN}
   \texttt{ACK} e sono settati.
   
@@ -72,10 +72,10 @@ seguente:
   è stabilita.
 \end{itemize} 
 
-Dato che per compiere tutto questo procedimento devono essere scambiati tre
-pacchetti esso viene generalmente chiamato \textit{three way handshake}. In
-\nfig\ si è rappresentato graficamente lo sequenza di scambio dei segmenti che
-stabilisce la connessione.
+Il procedimento viene chiamato \textit{three way handshake} dato che per
+realizzarlo devono essere scambiati tre segmenti.  In \nfig\ si è
+rappresentata graficamente la sequenza di scambio dei segmenti che stabilisce
+la connessione.
 
 % Una analogia citata da R. Stevens per la connessione TCP è quella con il
 % sistema del telefono. La funzione \texttt{socket} può essere considerata
@@ -93,17 +93,18 @@ stabilisce la connessione.
   \label{fig:TCPel_TWH}
 \end{figure}
 
-Si noti che figura si sono riportati anche i \textsl{numeri di sequenza}
-associati ai vari pacchetti; per gestire una connessione affidabile infatti il
-protocollo TCP prevede nell'header la presenza di un \textit{sequence number}
-a 32 bit che identifica a quale byte nella sequenza dello stream corrisponde
-il primo byte dei dati contenuti nel segmento.
+Si è accennato in precedenza ai \textsl{numeri di sequenza} (che sono anche
+riportati in \curfig); per gestire una connessione affidabile infatti il
+protocollo TCP prevede nell'header la presenza di un numero a 32 bit (chiamato
+appunto \textit{sequence number}) che identifica a quale byte nella sequenza
+del flusso corrisponde il primo byte della sezione dati contenuta nel
+segmento.
 
 Il numero di sequenza di ciascun segmento viene calcolato a partire da un
-numero di sequenza iniziale generato in maniera casuale del kernel all'inizio
-della connessione e trasmesso con il SYN; l'acknowledgement di ciascun
-segmento viene effettuato dall'altro capo della connessione settando il flag
-\texttt{ACK} e restituendo nell'apposito campo dell'header un
+\textsl{numero di sequenza iniziale} generato in maniera casuale del kernel
+all'inizio della connessione e trasmesso con il SYN; l'acknowledgement di
+ciascun segmento viene effettuato dall'altro capo della connessione settando
+il flag \texttt{ACK} e restituendo nell'apposito campo dell'header un
 \textit{acknowledge number}) pari al numero di sequenza che il ricevente si
 aspetta di ricevere con il pacchetto successivo; dato che il primo pacchetto
 SYN consuma un byte, nel \textit{three way handshake} il numero di acknowledge
@@ -113,9 +114,10 @@ varr
 \subsection{Le opzioni TCP.}
 \label{sec:TCPel_TCP_opt}
 
-Ciascun SYN può contenere delle opzioni per il TCP (le cosiddette \textit{TCP
-  options}, che vengono inserite fra l'header e i dati) che servono a regolare
-la connessione. Normalmente vengono usate le seguenti opzioni:
+Ciascun segmento SYN contiene in genere delle opzioni per il protocollo TCP
+(le cosiddette \textit{TCP options}, che vengono inserite fra l'header e i
+dati) che servono a comunicare all'altro capo una serie di parametri utili a
+regolare la connessione. Normalmente vengono usate le seguenti opzioni:
 
 \begin{itemize}
 \item \textit{MSS option} Sta per \textit{maximum segment size}, con questa
@@ -129,7 +131,9 @@ la connessione. Normalmente vengono usate le seguenti opzioni:
   \textsl{finestra annunciata} (\textit{advertized window}) con la quale
   ciascun capo della comunicazione dichiara quanto spazio disponibile ha in
   memoria per i dati. Questo è un numero a 16 bit dell'haeader, che così può
-  indicare un massimo di 65535 bytes; ma alcuni tipi di connessione come
+  indicare un massimo di 65535 bytes (anche se linux usa come massimo 32767
+  per evitare problemi con alcuni stack bacati che usano l'aritmetica con
+  segno per implementare lo stack TCP); ma alcuni tipi di connessione come
   quelle ad alta velocità (sopra i 45Mbits/sec) e quelle che hanno grandi
   ritardi nel cammino dei pacchetti (come i satelliti) richiedono una finestra
   più grande per poter ottenere il massimo dalla trasmissione, per questo
@@ -140,7 +144,7 @@ la connessione. Normalmente vengono usate le seguenti opzioni:
     connessione riconosca esplicitamente l'opzione inserendola anche lui nel
     suo SYN di risposta dell'apertura della connessione} per la connessione
   corrente (espresso come numero di bit cui shiftare a sinistra il valore
-  della finestra annunciata).
+  della finestra annunciata inserito nel pacchetto).
 
 \item \textit{timestamp option} è anche questa una nuova opzione necessaria
   per le connessioni ad alta velocità per evitare possibili corruzioni di dati
@@ -153,15 +157,16 @@ La MSS 
 protocollo, le ultime due opzioni (trattate nell'RFC 1323) sono meno comuni;
 vengono anche dette \textit{long fat pipe options} dato che questo è il nome
 che viene dato alle connessioni caratterizzate da alta velocità o da ritardi
-elevati.
-
+elevati. In ogni caso linux supporta pienamente entrambe le opzioni.
 
 \subsection{La terminazione della connessione}
 \label{sec:TCPel_conn_term}
 
 Mentre per creare una connessione occorre un interscambio di tre segmenti, la
-procedura di chiusura ne richede ben quattro; in questo caso la successione
-degli eventi è la seguente:
+procedura di chiusura ne richede quattro; ancora una volta si può fare
+riferimento al codice degli esempi \ref{fig:net_cli_code} e
+\ref{fig:net_serv_code}, in questo caso la successione degli eventi è la
+seguente:
 
 \begin{enumerate}
 \item Un processo ad uno dei due capi chiama la funzione \texttt{close}, dando
@@ -208,43 +213,504 @@ che si mantenga un flusso di dati dal capo della connessione che sta eseguendo
 la chiusura passiva a quello che sta eseguendo la chiusura attiva. Nella
 sequenza indicata i dati verrebbero persi, dato che si è chiuso il socket, ma
 esistono situazione in cui si vuole che avvenga proprio questo, che è chiamato
-\texit{half-close}, per cui torneremo su questo aspetto e su come utilizzarlo
+\textit{half-close}, per cui torneremo su questo aspetto e su come utilizzarlo
 più avanti, quando parleremo della funzione \texttt{shutdown}.
 
 La emissione del FIN avviene quando il socket viene chiuso, questo però non
-avviene solo per la chiamata della funzione \texttt{close}, ma anche alla
-terminazione di un processo, il che vuol dire che se un processo viene
+avviene solo per la chiamata della funzione \texttt{close} (come in
+\ref{fig:net_serv_code}), ma anche alla terminazione di un processo (come in
+\ref{fig:net_cli_code}). Questo vuol dire ad esempio che se un processo viene
 terminato da un segnale tutte le connessioni aperte verranno chiuse.
 
+Infine è da sottolineare che, benché nella figura (e nell'esempio che vedremo
+in \ref{sec:TCPel_echo_example}) sia il client ad eseguire la chiusura attiva,
+nella realtà questa può essere eseguita da uno qualunque dei due capi della
+comunicazione (come in fatto in precedenza da \ref{fig:net_serv_code}), e
+benché quello del client sia il caso più comune ci sono alcuni servizi, il
+principale dei quali è l'HTTP, per i quali è il server ad effettuare la
+chiusura attiva.
+
 
 \subsection{Un esempio di connessione}
 \label{sec:TCPel_conn_dia}
 
 Le operazioni del TCP nella creazione e conclusione di una connessione sono
 specificate attraverso il diagramma di transizione degli stati riportato in
-\nfig. TCP prevede l'esistenza di 11 diversi stati per una connessione ed un
-insieme di regole per le transizioni da uno stato all'altro basate sullo stato
-corrente e sul tipo di segmetno ricevuto.
+\nfig. TCP prevede l'esistenza di 11 diversi stati per un socket ed un insieme
+di regole per le transizioni da uno stato all'altro basate sullo stato
+corrente e sul tipo di segmento ricevuto; i nomi degli stati sono gli stessi
+che vengono riportati del comando \texttt{netstat} nel campo \textit{State}.
+
+Una descrizione completa del funzionamento del protocollo va al di là degli
+obiettivi di questo libro; un approfondimento sugli aspetti principali si
+trova in \ref{cha:tcp_protocol}, ma per una trattazione esauriente il miglior
+riferimento resta (FIXME citare lo Stevens); qui ci limiteremo a descrivere
+brevemente un semplice esempio di connessione e le transizioni che avvengono
+nei due casi appena citati (creazione e terminazione della connessione).
+
+In assenza di connessione lo stato del TCP è \textsl{CLOSED}; quando una
+applicazione esegue una apertura attiva il TCP emette un SYN e lo stato
+diventa \textsl{SYN\_SENT}; quando il TCP riceve la risposta del SYN$+$ACK
+emette un ACK e passa allo stato \textsl{ESTABLISHED}; questo è lo stato
+finale in cui avviene la gran parte del trasferimento dei dati.
+
+Dal lato server in genere invece il passaggio che si opera con l'apertura
+passiva è quello di portare il socket dallo stato \textsl{CLOSED} allo
+stato \textsl{LISTEN} in cui vengono accettate le connessioni.
+
+Dallo stato \textsl{ESTABLISHED} si può uscire in due modi; se un'applicazione
+chiama la \texttt{close} prima di aver ricevuto un end of file (chiusura
+attiva) la transizione è verso lo stato \textsl{FIN\_WAIT\_1}; se invece
+l'applicazione riceve un FIN nello stato \textsl{ESTABLISHED} (chiusura
+passiva) la transizione è verso lo stato \textsl{CLOSE\_WAIT}.
+
+In \nfig\ è riportato lo schema dello scambio dei pacchetti che avviene per
+una un esempio di connessione, insieme ai vari stati che il protocollo viene
+ad assumere per i due lati, server e client.
 
+\begin{figure}[htb]
+  \centering
+  
+  \caption{Schema dello scambio di pacchetti per un esempio di connessione}
+  \label{fig:TPCel_conn_example}
+\end{figure}
 
+La connessione viene iniziata dal client che annuncia un MSS di 1460 (un
+valore tipico per IPv4 su ethernet) con linux, il server risponde con lo
+stesso valore (ma potrebbe essere anche un valore diverso).
+
+Una volta che la connessione è stabilita il client scrive al server una
+richiesta (che assumiamo stare in un singolo segmento, cioè essere minore dei
+1460 bytes annunciati dal server), quest'ultimo riceve la richiesta e
+restituisce una risposta (che di nuovo supponiamo stare in un singolo
+segmento). Si noti che l'acknowledge della richiesta è mandato insieme alla
+risposta, questo viene chiamato \textit{piggybacking} ed avviene tutte le
+volte che che il server è sufficientemente veloce a costruire la risposta, in
+caso contrario si avrebbe prima l'emissione di un ACK e poi l'invio della
+risposta.
+
+Infine si ha lo scambio dei quattro segmenti che terminano la connessione
+secondo quanto visto in \ref{sec:TCPel_conn_term}; si noti che il capo della
+connessione che esegue la chiusura attiva entra nello stato
+\textsl{TIME\_WAIT} su cui torneremo fra poco.
+
+È da notare come per effettuare uno scambio di due pacchetti (uno di richiesta
+e uno di risposta) il TCP necessiti di ulteriori otto segmenti, se invece si
+fosse usato UDP sarebbero stati sufficienti due soli pacchetti. Questo è il
+costo che occorre pagare per avere l'affidabilità garantita dal TCP, se si
+fosse usato UDP si sarebbe dovuto trasferire la gestione di tutta una serie di
+dettagli (come la verifica della ricezione dei pacchetti) dal livello del
+trasporto all'interno dell'applicazione.
+
+Quello che è bene sempre tenere presente è allora quali sono le esigenze che
+si hanno in una applicazione di rete, perché non è detto che TCP sia la
+miglior scelta in tutti i casi (ad esempio se si devono solo scambiare dati
+già organizzati in piccoli pacchetti l'overhead aggiunto può essere eccessivo)
+per questo esistono applicazioni che usano UDP e lo fanno perché nel caso
+specifico le sue caratteristiche di velocità e compattezza nello scambio dei
+dati rispondono meglio alle esigenze che devono essere affrontate.
 
 \subsection{Lo stato \texttt{TIME\_WAIT}}
 \label{sec:TCPel_time_wait}
 
+Come riportato da Stevens (FIXME citare) lo stato \texttt{TIME\_WAIT} è
+probabilmente uno degli aspetti meno compresi del protocollo TCP, è infatti
+comune trovare nei newsgroup domande su come sia possibile evitare che
+un'applicazione resti in questo stato lasciando attiva una connessione ormai
+conclusa; la risposta è che non deve essere fatto, ed il motivo cercheremo di
+spiegarlo adesso.
+
+Come si è visto nell'esempio precedente (vedi \curfig) \texttt{TIME\_WAIT} è
+lo stato finale in cui il capo di una connessione che esegue la chiusura
+attiva resta prima di passare alla chiusura definitiva della connessione. Il
+tempo in cui l'applicazione resta in questo stato deve essere due volte la MSL
+(\textit{Maximum Segment Lifetime}). 
+
+La MSL è la stima del massimo periodo di tempo che un pacchetto IP può vivere
+sulla rete; questo tempo è limitato perché ogni pacchetto IP può essere
+ritrasmesso dai router un numero massimo di volte (detto \textit{hop limit}).
+Il numero di ritrasmissioni consentito è indicato dal campo TTL dell'header di
+IP (per maggiori dettagli vedi \ref{sec:appA_xxx}), e viene decrementato ad
+ogni passaggio da un router; quando si annulla il pacchetto viene scartato.
+Siccome il numero è ad 8 bit il numero massimo di ``salti'' è di 255, pertanto
+anche se il TTL (da \textit{time to live}) non è propriamente un limite sul
+tempo di vita, si stima che un pacchetto IP non possa restare nella rete per
+più di MSL secondi.
+
+Ogni implementazione del TCP deve scegliere un valore per la MSL (l'RFC1122
+raccomanda 2 minuti, linux usa 30 secondi), questo comporta una durata dello
+stato \textsl{TIME\_WAIT} che a seconda delle implementazioni può variare fra
+1 a 4 minuti.
+
+Lo stato \texttt{TIME\_WAIT} viene utilizzato dal protocollo per due motivi
+principali:
+\begin{itemize}
+\item implementare in maniera affidabile la terminazione della connessione
+  in entrambe le direzioni.
+\item consentire l'eliminazione dei segmenti duplicati dalla rete. 
+\end{itemize}
+
+Il punto è che entrambe le ragioni sono importanti, anche se spesso si fa
+riferimento solo alla prima; ma è solo se si tiene conto della seconda che si
+capisce il perché della scelta di un tempo pari al doppio della MSL come
+durata di questo stato.
+
+Il primo dei due motivi precedenti si può capire tornando a \curfig: assumendo
+che l'ultimo ACK della sequenza (quello del capo che ha eseguito la chiusura
+attiva) vanga perso, chi esegue la chiusura passiva non ricevndo risposta
+rimanderà un ulteriore FIN, per questo motivo chi esegue la chiusura attiva
+deve mantenere lo stato della connessione per essere in grado di reinviare
+l'ACK e chiuderla correttamente. Se non fosse così la risposta sarebbe un RST
+(un altro tipo si segmento) che verrebbe interpretato come un errore.
+
+Se il TCP deve poter chiudere in maniera pulita entrambe le direzioni della
+connessione allora deve essere in grado di affrontare la perdita di uno
+qualunque dei quattro segmenti che costituiscono la chiusura. Per questo
+motivo lo stato \texttt{TIME\_WAIT} deve essere mantenuto anche dopo l'invio
+dell'ultimo ACK per poter essere in grado di poterne gestire l'eventuale
+ritrasmissione in caso di perdita.
+
+
+Il secondo motivo è più complesso da capire, e necessita di spiegare meglio
+gli scenari in cui accade che i pacchetti si possono perdere nella rete o
+restare intrappolati, per poi riemergere.
+
+Il caso più comune in cui questo avviene è quello di anomalie
+nell'instradamento; può accadere cioè che un router smetta di funzionare o che
+una connessione fra due router si interrompa. In questo caso i protocolli di
+instradamento dei pacchetti possono impiegare diverso temo (anche dell'ordine
+dei minuti) prima di trovare e stabilire un percorso alternativo per i
+pacchetti. Nel frattempo possono accadere casi in cui un router manda i
+pacchetti verso un'altro e quest'ultimo li rispedisce indietro, o li manda ad
+un terzo router che li rispedisce al primo, si creano cioè dei circoli (i
+cosiddetti \textit{routing loop}) in cui restano intrappolati i pacchetti.
+
+Se uno di questi pacchetti intrappolati è un segmento di TCP chi l'ha inviato,
+non ricevendo risposta, provvederà alla ritrasmissione e se nel frattempo sarà
+stata stabilita una strada alternativa il pacchetto ritrasmesso giungerà a
+destinazione. Ma se dopo un po' di tempo (che non supera il limite dell'MSL)
+l'anomalia viene a cessare il circolo di instadamento viene spezzato i
+pacchetti intrappolati potranno essere inviati alla destinazione finale, con
+la conseguenza di avere dei pacchetti duplicati; questo è un caso che il TCP
+deve essere in grado di gestire.
+
+Allora per capire la seconda ragione per l'esistenza dello stato
+\texttt{TIME\_WAIT} si consideri il caso seguente: si supponga di avere una
+connessione fra l'IP 195.110.112.236 porta 1550 e l'IP 192.84.145.100 porta
+22, che questa venga chiusa e che poco dopo si ristabilisca la stessa
+connessione fra gli stessi IP sulle stesse porte (quella che viene detta,
+essendo gli stessi porte e numeri IP, una nuova \textsl{incarnazione} della
+connessione precedente); in questo caso ci si potrebbe trovare con dei
+pacchetti duplicati relativi alla precedente connessione che riappaiono nella
+nuova.
+
+Ma fintanto che il socket non è chiuso una nuova incarnazione non può essere
+creata, per questo un socket TCP resta sempre nello stato \texttt{TIME\_WAIT}
+per un periodo di 2MSL, in modo da attendere MSL secondi per essere sicuri che
+tutti i pacchetti duplicati in arrivo siano stati ricevuti (e scartati) o che
+nel frattempo siano stati eliminati dalla rete, e altri MSL secondi per essere
+sicuri che lo stesso avvenga le risposte nella direzione opposta.
+
+In questo modo il TCP si assicura che quando una viene creata una nuova
+connessione tutti gli eventuali segmenti residui di una precedente connessione
+che possono causare disturbi sono stati eliminati dalla rete.
+
+
+\subsection{I numeri di porta}
+\label{sec:TCPel_port_num}
+
+In un ambiente multitasking in un dato momento più processi possono dover
+usare sia UDP che TCP, e ci devono poter essere più connessioni in
+contemporanea. Per poter tenere distinte le diverse connessioni entrambi i
+protocolli usano i \textsl{numeri di porta}, che fanno parte, come si può
+vedere in \ref{sec:sock_sa_ipv4} e \ref{sec:sock_sa_ipv6} pure delle strutture
+degli indirizzi del socket.
+
+Quando un client contatta un server deve poter identificare con quale dei vari
+possibili server attivi intende parlare. Sia TCP che UDP definiscono un gruppo
+di \textsl{porte conosciute} (le cosiddette \textit{well-known port}) che
+identificano una serie di servizi noti (ad esempio la porta 22 identifica il
+servizio \texttt{ssh}) effettuati da appositi server che rispondono alle
+connessioni verso tali porte.
+
+D'altra parte un client non ha necessità di usare un numero di porta
+specifico, per cui in genere vengono usate le cosiddette \textsl{porte
+  effimere} (o \textit{ephemeral ports}) cioè porte a cui non è assegnato
+nessun servizio noto e che vengono assegnate automaticamente dal kernel alla
+creazione della connessione. Queste sono dette effimere in quanto vengono
+usate solo per la durata della connessione, e l'unico requisito che deve
+essere soddisfatto è che ognuna di esse sia assegnata in maniera univoca.
+
+La lista delle porte conosciute è definita dall'RFC1700 che contiene l'elenco
+delle porte assegnate dalla IANA (\textit{Internet Assigned Number Authority})
+ma l'elenco viene costantemente aggiornato e pubblicato all'indirizzo
+\texttt{ftp://ftp.isi.edu/in-notes/iana/assignements/port-numbers}, inoltre il
+file \texttt{/etc/services} contiene un analogo elenco, con la corrispondenza
+fra i numeri di porta ed il nome simbolico del servizio. I numeri sono divisi
+in tre intervalli:
 
+\begin{enumerate}
+\item \textsl{le porte conosciute}. I numeri da 0 a 1023. Queste sono
+  controllate e assegnate dalla IANA. Se è possibile la stessa porta è
+  assegnata allo stesso servizio sia su UDP che su TCP (ad esempio la porta 22
+  è assegnata a ssh su entrambi i protocolli, anche se viene usata solo dal
+  TCP).
+  
+\item \textsl{le porte registrate}. I numeri da 1024 a 49151. Queste porte non
+  sono controllate dalla IANA, che però registra ed elenca chi usa queste
+  porte come servizio agli utenti. Come per le precedenti si assegna una porta
+  ad un servizio sia per TCP che UDP anche se poi il servizio è implementato
+  solo su TCP. Ad esempio X Window usa le porte TCP e UDP dal 6000 al 6063
+  anche se il protocollo è implementato solo tramite TCP.
+  
+\item \textsl{le porte private} o \textsl{dinamiche}. I numeri da 49152 a
+  65535. La IANA non dice nulla riguardo a queste porte che pertanto
+  sono i candidati naturali ad essere usate come porte effimere.
+\end{enumerate}
+
+In realtà rispetto a quanto indicato nell'RFC1700 i vari sistemi hanno fatto
+scelte diverse per le porte effimere, in particolare in \nfig\ sono riportate
+quelle di BSD, Solaris e linux. Nel caso di linux poi la scelta fra i due
+intervali possibili viene fatta dinamicamente a seconda della memoria a
+disposizione del kernel per gestire le rative tabelle.
+
+\begin{figure}[!htb]
+  \centering
+  
+  \caption{Allocazione dei numeri di porta}
+  \label{fig:TCPel_port_alloc}
+\end{figure}
+
+I sistemi unix hanno inoltre il concetto di \textsl{porte riservate} (che
+corrispondono alle porte con numero minore di 1024 e coincidono quindi con le
+porte conosciute). La loro caratteristica è che possono essere assegnate a un
+socket solo da un processo con i privilegi di root, per far si che solo
+l'amministratore possa allocare queste porte per far partire relativi servizi.
+
+Si tenga conto poi che ci sono alcuni client (in particolare \texttt{rsh} e
+\texttt{rlogin}) che richiedono una connessione su una porta riservata anche
+dal lato client come parte dell'autenticazione. Questo viene fatto tramite la
+funzione \texttt{rresvport} assegnando al socket una porta libera
+nell'intervallo fra 512 e 1023.
+
+Data una connessione TCP si suole chiamare \textit{socket pair} la
+combinazione dei quattro numeri che definiscono i due capi della connessione e
+cioè l'indirizzo IP locale e la porta TCP locale, e l'indirizzo IP remoto e la
+porta TCP remota; questa combinazione, che scriveremo usando una notazione del
+tipo $(195.110.112.152:22, 192.84.146.100:20100)$, identifica univocamente una
+connessione su internet. Questo concetto viene di solito esteso anche a UDP,
+benché in questo caso non abbia senso parlare di connessione. L'utilizzo del
+programma \texttt{netstat} permette di visualizzare queste informazioni nei
+campi \textit{Local Address} e \textit{Foreing Address}.
+
+
+\subsection{Le porte ed il modello client/server}
+\label{sec:TCPel_port_cliserv}
+
+Per capire meglio l'uso delle porte e come vengono utilizzate nella
+programmazione di rete consideriamo cosa accade con una serie di esempi, se
+esguiamo un \texttt{netstat} su una macchina di prova (che supponiamo avere
+indirizzo 195.110.112.152) potremo avere un risultato del tipo:
+\begin{verbatim}
+Active Internet connections (servers and established)
+Proto Recv-Q Send-Q Local Address           Foreign Address         State      
+tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
+tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN
+tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN
+\end{verbatim}
+essendo presenti un server ssh, un server di posta e un DNS per il caching
+locale. 
+
+Questo ci mostra ad esempio che il server ssh ha compiuto un'apertura passiva
+mettendosi in ascolto sulla porta 22 riservata a questo servizio e che si è
+posto in ascolto per connessioni provenienti da uno qualunque degli indirizzi
+associati alle interfaccie locali; la notazione 0.0.0.0 usata da netstat è
+equivalente all'asterisco utilizzato per il numero di porta ed indica il
+valore generico, e corrisponde al valore \texttt{INADDR\_ANY} definito in
+\texttt{arpa/inet.h}.
+
+Inoltre la porta e l'indirizzo di ogni eventuale connessione esterna non sono
+specificati; in questo caso la \textit{socket pair} associata al socket può
+essere indicata come $(*:22, *.*)$, usando l'asterisco anche per gli indirizzi
+come carattere di \textit{wildchard}. 
+
+In genere avendo le macchine associato un solo IP ci si può chiedere che senso
+abbia l'utilizzo dell'indirizzo generico per l'indirizzo locale, ma esistono
+anche macchine che hanno più di un indirizzo IP (il cosiddetto
+\textit{miltihoming}) in questo modo si possono accettare connessioni
+indirizzate verso uno qualunque di essi. Ma come si può vedere nell'esempio
+con il DNS in ascolto sulla porta 53 è anche possibile restringere l'accesso
+solo alle connessioni che provengono da uno specifico indirizzo, cosa che nel
+caso è fatta accettando solo connessioni che arrivino sull'interfaccia di
+loopback.
+
+Una volta che ci si vorrà collegare a questa macchina da un'altra posta
+all'indirizzo 192.84.146.100 si potrà lanciare un client \texttt{ssh} per
+creare una connessione verso la precedente, e il kernel associerà al suddetto
+una porta effimera che per esempio potrà essere la 21100, la connessione
+allora sarà espressa dalla socket pair $(192.84.146.100:21100,
+195.110.112.152.22)$.
+
+Alla ricezione della richiesta dal client il server creerà un processo figlio
+per gestire la connessione, se a questo punto eseguiamo nuovamente il
+programma netstat otterremo come risultato:
+\begin{verbatim}
+Active Internet connections (servers and established)
+Proto Recv-Q Send-Q Local Address           Foreign Address         State      
+tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
+tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN
+tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN
+tcp        0      0 195.110.112.152:22      192.84.146.100:21100    ESTABLISHED
+\end{verbatim}
+
+Come si può notare il server è ancora in ascolto sulla porta 22, però adesso
+c'è un nuovo socket (con lo stato \texttt{ESTABLISHED}) che anch'esso utilizza
+la porta 22, ma ha specificato l'indirizzo locale, e che corrisponde al socket
+con cui il processo figlio gestisce la connessione mentre il padre resta in
+ascolto.
+
+Se a questo lanciamo una seconda volta il client ssh per una seconda
+conessione quello che otterremo sarà qualcosa del genere:
+\begin{verbatim}
+Active Internet connections (servers and established)
+Proto Recv-Q Send-Q Local Address           Foreign Address         State      
+tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
+tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN
+tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN
+tcp        0      0 195.110.112.152:22      192.84.146.100:21100    ESTABLISHED
+tcp        0      0 195.110.112.152:22      192.84.146.100:21101    ESTABLISHED
+\end{verbatim}
+cioè al client sarà stata assegnata un'altra porta effimera e con questa sarà
+aperta la connessione, ed un nuovo processo figlio sarà creato per gestirla.
+
+
+Tutto ciò mostra come TCP, per poter gestire le due connessioni, non può
+suddividere i pacchetti solo sulla base della porta di destinazione, ma deve
+usare tutta l'informazione contenuta nella socket pair, compresa la porta
+dell'indirizzo remoto.  E se andassimo a vedere quali sono i processi a cui
+fanno riferimento i vari socket vedremmo che i pacchetti che arrivano dalla
+porta remota 21100 vanno al primo figlio e quelli che arrivano alla porta
+21101 al secondo.
 
-\section{I numeri di porta}
-\label{sec:TCPel_ports}
 
 \section{Le funzioni dei socket TCP}
 \label{sec:TCPel_functions}
 
+In questa sezione descriveremo in dettaglio le varie funzioni necessarie per
+l'uso dei socket TCP già citate in precedenza (e utilizzate nei due esempi
+\ref{sec:net_cli_sample} e \ref{sec:net_serv_sample}) con l'eccezione della
+funzione \texttt{socket} che è già stata esaminata in dettaglio in
+\ref{sec:sock_socket}.
+
+In \nfig\ abbiamo un tipico schema di funzionamento di un'applicazione
+client-server che usa i socket TCP: prima il server viene avviato ed in
+seguito il client si connette, in questo caso, a differenza di quanto accadeva
+con gli esempi elementari del Cap.~\ref{cha:network} si assume che sia il
+client ad effettuare delle richieste a cui il server risponde, il client
+notifica poi di avere concluso inviando un end-of-file a cui il server
+risponderà anche lui chiudendo la connessione per aspettarne una nuova.
+
+\begin{figure}[!htb]
+  \centering
+
+  \caption{Struttura delle funzioni dei socket per una semplice applicazione
+    client/server su TCP.}
+  \label{fig:TCPel_cliserv_func}
+\end{figure}
+
+Useremo questo schema per l'esempio di implementazione del servizio
+\texttt{echo} che illustreremo in \ref{sec:TCPel_echo_example}. 
+
 \subsection{La funzione \texttt{connect}}
 \label{sec:TCPel_func_connect}
 
+La funzione \texttt{connect} è usata da un client TCP per stabilire la
+connessione con un server TCP, il prototipo della funzione, definito in
+\texttt{sys/socket.h}, è il seguente:
+
+\begin{itemize}
+\item \texttt{int connect(int sockfd, const struct sockaddr *serv_addr,
+    socklen_t addrlen) }
+  
+  Il primo argomento è un file descriptor ottenuto da una precedente chiamata
+  a \texttt{socket}, mentre il secondo e terzo argomento sono rispettivamente
+  l'indirizzo e la dimensione della struttura che contiene l'indirizzo del
+  socket, già descritta in \ref{sec:sock_sockaddr}.
+
+  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
+  di errore. La variabile \texttt{errno} viene settata secondo i seguenti
+  codici di errore
+
+  \begin{itemize}
+  \item \texttt{EBADF} Il file descriptor non è valido.
+  \item \texttt{EFAULT} L'indirizzo della struttura di indirizzi è al di fuori
+    dello spazio di indirizzi dell'utente.
+  \item \texttt{ENOTSOCK} Il file descriptor non è associato ad un socket
+  \item \texttt{EISCONN} Il socket è già connesso.
+  \item \texttt{ECONNREFUSED} Non c'è nessuno in ascolto sull'indirizzo remoto.
+  \item \texttt{ETIMEDOUT} Si è avuto timeout durante il tentativo di
+    connessione.
+  \item \texttt{ENETUNREACH} La rete non è rggiungibile/
+  \item \texttt{EADDRINUSE} L'indirizzo locale è in uso.
+  \item \texttt{EINPROGRESS} Il socket è non bloccante e la connessione non
+    può essere conclusa immediatamente.
+  \item \texttt{EALREADY} Il socket è non bloccante e un tentativo precedente
+    di connessione non si è ancora concluso.
+  \item \texttt{EAGAIN} Non ci sono più porte locali libere. 
+  \item \texttt{EAFNOSUPPORT} L'indirizzo non ha una famiglia di indirizzi
+    corretta nel relativo campo.
+  \item \texttt{EACCESS, EPERM} 
+  \end{itemize}
+\end{itemize}
+
+La struttura dell'indirizzo deve essere inizializzata con l'indirizzo IP e il
+numero di porta del server a cui ci si vuole connettere, come mostrato
+nell'esempio \ref{sec:net_cli_sample} usando le funzioni illustrate in
+\ref{sec:sock_addr_func}.
+
+Nel caso di socket TCP la funzione \texttt{connect} avvia il three way
+handshake, e ritorna solo quando la connessione è stabilita o si è verificato
+un errore. Le possibili cause di errore sono molteplici (e brevemente
+riassunte sopra), in particolare le principali sono:
+
+\begin{enumerate}
+\item Se il client non riceve risposta al SYN l'errore restituito è
+  \texttt{ETIMEDOUT}. Stevens riporta che BSD invia un primo SYN alla chiamata
+  di \texttt{connect}, un'altro dopo 6 secondi, un terzo dopo 24 secondi, se
+  dopo 75 secondi non ha ricevuto risposta viene ritornato l'errore. Linux
+  invece ripete l'emissione del SYN ad intervalli di 30 secondi per un numero
+  di volte che può essere stabilito dall'utente sia con una opportuna
+  \texttt{sysctl} che attraverso il filesystem \texttt{/proc} scrivendo il
+  valore voluto in \texttt{/proc/sys/net/ipv4/tcp_syn_retries}. Il valore di
+  default per la ripetizione dell'invio è di 5 volte, che comporta un timeout
+  dopo circa 180 secondi.
+%
+% Le informazioni su tutte le opzioni settabili via /proc stanno in
+% linux/Documentation/networking/ip-sysctl.txt
+%
+\item Se il client riceve come risposta al SYN un RST significa che non c'è
+  nessun programma in ascolto per la connessione sulla porta specificata (il
+  che vuol dire probablmente che o si è sbagliato il numero della porta o che
+  non è stato avviato il server), questo è un errore fatale e la funzione
+  ritorna non appena il RST viene ricevuto riportando un errore
+  \texttt{ECONNREFUSED}.
+  
+  Il flag RST sta per \textit{reset} ed è un segmento inviato direttamente
+  dal TCP quando qualcosa non va. Tre condizioni che generano un RST sono:
+  quando arriva un SYN per una porta che non ha nessun server in ascolto,
+  quando il TCP abortisce una connessione in corso, quandi TCP riceve un
+  segmento per una connessione che non esiste.
+
+\item Il SYN del client provoca l'emissione di un messaggio ICMP di
+  destinazione non raggiungibile. 
+  
+\end{enumerate}
+
 \subsection{La funzione \texttt{bind}}
 \label{sec:TCPel_func_bind}
 
+
+
 \subsection{La funzione \texttt{listen}}
 \label{sec:TCPel_func_listen}
 
@@ -252,7 +718,10 @@ corrente e sul tipo di segmetno ricevuto.
 \label{sec:TCPel_func_accept}
 
 
-\subsection{Le porte}
+\section{Una semplice implementazione del servizio \textt{echo} su TCP}
+\label{sec:TCPel_echo_example}
+