+++ /dev/null
-%% elemtcp.tex
-%%
-%% Copyright (C) 2000-2003 Simone Piccardi. Permission is granted to
-%% copy, distribute and/or modify this document under the terms of the GNU Free
-%% Documentation License, Version 1.1 or any later version published by the
-%% Free Software Foundation; with the Invariant Sections being "Prefazione",
-%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the
-%% license is included in the section entitled "GNU Free Documentation
-%% License".
-%%
-\chapter{Socket TCP}
-\label{cha:TCP_socket}
-
-In questo capitolo iniziamo ad approfondire la conoscenza dei socket TCP,
-iniziando con una descrizione delle principali caratteristiche del
-funzionamento di una connessione TCP. Tratteremo poi le varie funzioni che
-servono alla creazione di una connessione fra un server elementare ed il suo
-client, fornendo poi alcuni esempi di applicazione elementare.
-
-
-
-\section{Il funzionamento di una connessione TCP}
-\label{sec:TCP_connession}
-
-Prima di entrare nei dettagli delle singole funzioni usate nelle applicazioni
-che utilizzano i socket TCP, è fondamentale spiegare alcune delle basi del
-funzionamento del protocollo, poiché questa conoscenza è essenziale per
-comprendere il comportamento di dette funzioni per questo tipo di socket, ed
-il relativo modello di programmazione.
-
-Si ricordi che il protocollo TCP serve a creare degli \textit{stream socket},
-cioè una forma di canale di comunicazione che stabilisce una connessione
-stabile fra due stazioni, in modo che queste possano scambiarsi dei dati. In
-questa sezione ci concentreremo sulle modalità con le quali il protocollo dà
-inizio e conclude una connessione e faremo inoltre un breve accenno al
-significato di alcuni dei vari \textsl{stati} ad essa associati.
-
-\subsection{La creazione della connessione: il \textit{three way handshake}}
-\label{sec:TCP_conn_cre}
-
-Il processo che porta a creare una connessione TCP è chiamato \textit{three
- way handshake}; la successione tipica degli eventi (e dei
-\textsl{segmenti}\footnote{Si ricordi che il segmento è l'unità elementare di
- dati trasmessa dal protocollo TCP al livello successivo; tutti i segmenti
- hanno un header che contiene le informazioni che servono allo \textit{stack
- TCP} (così viene di solito chiamata la parte del kernel che implementa il
- protocollo) per realizzare la comunicazione, fra questi dati ci sono una
- serie di flag usati per gestire la connessione, come SYN, ACK, URG, FIN,
- alcuni di essi, come SYN (che sta per \textit{syncronize}) corrispondono a
- funzioni particolari del protocollo e danno il nome al segmento, (per
- maggiori dettagli vedere \secref{sec:tcp_protocol}).} di dati che vengono
-scambiati) che porta alla creazione di una connessione è la seguente:
-
-\begin{enumerate}
-\item Il server deve essere preparato per accettare le connessioni in arrivo;
- il procedimento si chiama \textsl{apertura passiva} del socket (in inglese
- \textit{passive open}). Questo viene fatto chiamando la sequenza di funzioni
- \func{socket}, \func{bind} e \func{listen}. Completata l'apertura passiva il
- server chiama la funzione \func{accept} e il processo si blocca in attesa di
- connessioni.
-
-\item Il client richiede l'inizio della connessione usando la funzione
- \func{connect}, attraverso un procedimento che viene chiamato
- \textsl{apertura attiva}, dall'inglese \textit{active open}. La chiamata di
- \func{connect} blocca il processo e causa l'invio da parte del client di un
- segmento SYN, in sostanza viene inviato al server un pacchetto IP che
- contiene solo gli header IP e TCP (con il numero di sequenza iniziale e il
- flag SYN) e le opzioni di TCP.
-
-\item il server deve dare ricevuto (l'\textit{acknowledge}) del SYN del
- client, inoltre anche il server deve inviare il suo SYN al client (e
- trasmettere il suo numero di sequenza iniziale) questo viene fatto
- ritrasmettendo un singolo segmento in cui sono impostati entrambi i flag SYN
- e ACK.
-
-\item una volta che il client ha ricevuto l'acknowledge dal server la funzione
- \func{connect} ritorna, l'ultimo passo è dare dare il ricevuto del SYN del
- server inviando un ACK. Alla ricezione di quest'ultimo la funzione
- \func{accept} del server ritorna e la connessione è stabilita.
-\end{enumerate}
-
-Il procedimento viene chiamato \textit{three way handshake} dato che per
-realizzarlo devono essere scambiati tre segmenti. In \figref{fig:TCP_TWH}
-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
-% l'equivalente di avere un telefono. La funzione \texttt{bind} è analoga al
-% dire alle altre persone qual'è il proprio numero di telefono perché possano
-% chiamare. La funzione \texttt{listen} è accendere il campanello del telefono
-% per sentire le chiamate in arrivo. La funzione \texttt{connect} richiede di
-% conoscere il numero di chi si vuole chiamare. La funzione \texttt{accept} è
-% quando si risponde al telefono.
-
-\begin{figure}[htb]
- \centering
- \includegraphics[width=10cm]{img/three_way_handshake}
- \caption{Il \textit{three way handshake} del TCP.}
- \label{fig:TCP_TWH}
-\end{figure}
-
-Si è accennato in precedenza ai \textsl{numeri di sequenza} (che sono anche
-riportati in \figref{fig:TCP_TWH}): 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
-\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 impostando
-il flag 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
-è sempre pari al numero di sequenza iniziale incrementato di uno; lo stesso
-varrà anche (vedi \figref{fig:TCP_close}) per l'acknowledgement di un FIN.
-
-\subsection{Le opzioni TCP.}
-\label{sec:TCP_TCP_opt}
-
-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}, dove MMS sta per \textit{maximum segment size}, con
- questa opzione ciascun capo della connessione annuncia all'altro il massimo
- ammontare di dati che vorrebbe accettare per ciascun segmento nella
- connessione corrente. È possibile leggere e scrivere questo valore
- attraverso l'opzione del socket \const{TCP\_MAXSEG}.
-
-\item \textit{window scale option}, %come spiegato in \secref{sec:tcp_protocol}
- il protocollo TCP implementa il controllo di flusso attraverso una
- \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'header, che così può
- indicare un massimo di 65535 byte;\footnote{ Linux usa come massimo 32767
- per evitare problemi con alcune implementazioni che usano l'aritmetica con
- segno per implementare lo stack TCP.} ma alcuni tipi di connessione come
- quelle ad alta velocità (sopra i 45Mbit/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
- esiste questa opzione che indica un fattore di scala da applicare al valore
- della finestra annunciata\footnote{essendo una nuova opzione per garantire
- la compatibilità con delle vecchie implementazioni del protocollo la
- procedura che la attiva prevede come negoziazione che l'altro capo della
- 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 spostare a sinistra il valore
- 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
- dovute a pacchetti perduti che riappaiono; anche questa viene negoziata come
- la precedente.
-
-\end{itemize}
-
-La MSS è generalmente supportata da quasi tutte le implementazioni del
-protocollo, le ultime due opzioni (trattate
-nell'\href{http://www.ietf.org/rfc/rfc1323.txt}{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. In ogni caso Linux supporta pienamente entrambe le opzioni.
-
-\subsection{La terminazione della connessione}
-\label{sec:TCP_conn_term}
-
-Mentre per la creazione di una connessione occorre un interscambio di tre
-segmenti, la procedura di chiusura ne richiede normalmente quattro. In questo
-caso la successione degli eventi è la seguente:
-
-\begin{enumerate}
-\item Un processo ad uno dei due capi chiama la funzione \func{close}, dando
- l'avvio a quella che viene chiamata \textsl{chiusura attiva} (o
- \textit{active close}). Questo comporta l'emissione di un segmento FIN, che
- serve ad indicare che si è finito con l'invio dei dati sulla connessione.
-
-\item L'altro capo della connessione riceve il FIN e dovrà eseguire la
- \textsl{chiusura passiva} (o \textit{passive close}). Al FIN, come ad ogni
- altro pacchetto, viene risposto con un ACK, inoltre il ricevimento del FIN
- viene segnalato al processo che ha aperto il socket (dopo che ogni altro
- eventuale dato rimasto in coda è stato ricevuto) come un end-of-file sulla
- lettura: questo perché il ricevimento di un FIN significa che non si
- riceveranno altri dati sulla connessione.
-
-\item Una volta rilevata l'end-of-file anche il secondo processo chiamerà la
- funzione \func{close} sul proprio socket, causando l'emissione di un altro
- segmento FIN.
-
-\item L'altro capo della connessione riceverà il FIN conclusivo e risponderà
- con un ACK.
-\end{enumerate}
-
-Dato che in questo caso sono richiesti un FIN ed un ACK per ciascuna direzione
-normalmente i segmenti scambiati sono quattro. Questo non è vero sempre
-giacché in alcune situazioni il FIN del passo 1) è inviato insieme a dei dati.
-Inoltre è possibile che i segmenti inviati nei passi 2 e 3 dal capo che
-effettua la chiusura passiva, siano accorpati in un singolo segmento. In
-\figref{fig:TCP_close} si è rappresentato graficamente lo sequenza di
-scambio dei segmenti che conclude la connessione.
-
-\begin{figure}[htb]
- \centering
- \includegraphics[width=10cm]{img/tcp_close}
- \caption{La chiusura di una connessione TCP.}
- \label{fig:TCP_close}
-\end{figure}
-
-Come per il SYN anche il FIN occupa un byte nel numero di sequenza, per cui
-l'ACK riporterà un \textit{acknowledge number} incrementato di uno.
-
-Si noti che, nella sequenza di chiusura, fra i passi 2 e 3, è in teoria
-possibile che si mantenga un flusso di dati dal capo della connessione che
-deve ancora eseguire la chiusura passiva a quello che sta eseguendo la
-chiusura attiva. Nella sequenza indicata i dati verrebbero persi, dato che si
-è chiuso il socket dal lato che esegue la chiusura attiva; esistono tuttavia
-situazioni in cui si vuole poter sfruttare questa possibilità, usando una
-procedura che è chiamata \textit{half-close}; torneremo su questo aspetto e su
-come utilizzarlo in \secref{xxx_shutdown}, quando parleremo della funzione
-\func{shutdown}.
-
-La emissione del FIN avviene quando il socket viene chiuso, questo però non
-avviene solo per la chiamata esplicita della funzione \func{close}, ma anche
-alla terminazione di un processo, quando tutti i file vengono chiusi. Questo
-comporta ad esempio che se un processo viene terminato da un segnale tutte le
-connessioni aperte verranno chiuse.
-
-Infine occorre sottolineare che, benché nella figura (e nell'esempio che
-vedremo più avanti in \secref{sec:TCP_echo}) sia stato il client ad eseguire
-la chiusura attiva, nella realtà questa può essere eseguita da uno qualunque
-dei due capi della comunicazione (come nell'esempio di
-\figref{fig:TCP_daytime_iter_server_code}), e anche se il caso più comune
-resta quello del client, 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:TCP_conn_dia}
-
-Come abbiamo visto le operazioni del TCP nella creazione e conclusione di una
-connessione sono piuttosto complesse, ed abbiamo esaminato soltanto quelle
-relative ad un andamento normale. In \secref{sec:TCP_states} vedremo con
-maggiori dettagli che una connessione può assumere vari stati, che ne
-caratterizzano il funzionamento, e che sono quelli che vengono riportati dal
-comando \cmd{netstat}, per ciascun socket TCP aperto, nel campo
-\textit{State}.
-
-Non possiamo affrontare qui una descrizione completa del funzionamento del
-protocollo; un approfondimento sugli aspetti principali si trova in
-\secref{sec:tcp_protocol}, ma per una trattazione completa il miglior
-riferimento resta \cite{TCPIll1}. 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 è \texttt{CLOSED}; quando una
-applicazione esegue una apertura attiva il TCP emette un SYN e lo stato
-diventa \texttt{SYN\_SENT}; quando il TCP riceve la risposta del SYN$+$ACK
-emette un ACK e passa allo stato \texttt{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 \texttt{CLOSED} allo
-stato \texttt{LISTEN} in cui vengono accettate le connessioni.
-
-Dallo stato \texttt{ESTABLISHED} si può uscire in due modi; se un'applicazione
-chiama la funzione \texttt{close} prima di aver ricevuto un
-\textit{end-of-file} (chiusura attiva) la transizione è verso lo stato
-\texttt{FIN\_WAIT\_1}; se invece l'applicazione riceve un FIN nello stato
-\texttt{ESTABLISHED} (chiusura passiva) la transizione è verso lo stato
-\texttt{CLOSE\_WAIT}.
-
-In \figref{fig:TCP_conn_example} è 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
- \includegraphics[width=9cm]{img/tcp_connection}
- \caption{Schema dello scambio di pacchetti per un esempio di connessione.}
- \label{fig:TCP_conn_example}
-\end{figure}
-
-La connessione viene iniziata dal client che annuncia un MSS di 1460, un
-valore tipico con Linux per IPv4 su Ethernet, 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 byte 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 \secref{sec:TCP_conn_term}; si noti che il capo della
-connessione che esegue la chiusura attiva entra nello stato
-\texttt{TIME\_WAIT}, sul cui significato 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:TCP_time_wait}
-
-Come riportato da Stevens in \cite{UNP1} lo stato \texttt{TIME\_WAIT} è
-probabilmente uno degli aspetti meno compresi del protocollo TCP, è infatti
-comune trovare 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 \figref{fig:TCP_conn_example})
-\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 \secref{sec:IP_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 ``\textsl{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'\href{http://www.ietf.org/rfc/rfc1122.txt}{RFC~1122} raccomanda 2 minuti,
-Linux usa 30 secondi), questo comporta una durata dello stato
-\texttt{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{enumerate}
-\item implementare in maniera affidabile la terminazione della connessione
- in entrambe le direzioni.
-\item consentire l'eliminazione dei segmenti duplicati dalla rete.
-\end{enumerate}
-
-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
-\figref{fig:TCP_conn_example}: assumendo che l'ultimo ACK della sequenza
-(quello del capo che ha eseguito la chiusura attiva) vanga perso, chi esegue
-la chiusura passiva non ricevendo 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 un socket deve rimanere attivo nello stato \texttt{TIME\_WAIT} anche
-dopo l'invio dell'ultimo ACK, per potere essere in grado di gestirne
-l'eventuale ritrasmissione, in caso esso venga perduto.
-
-Il secondo motivo è più complesso da capire, e necessita di una spiegazione
-degli scenari in cui può accadere che i pacchetti TCP si possano perdere nella
-rete o restare intrappolati, per poi riemergere in un secondo tempo.
-
-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 tempo (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 TCP, chi l'ha inviato,
-non ricevendo un ACK in 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, dato che
-altrimenti verrebbe ecceduto il TTL) l'anomalia viene a cessare, il circolo di
-instradamento 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 \texttt{195.110.112.236} porta 1550 e l'IP
-\texttt{192.84.145.100} porta 22 (affronteremo il significato delle porte
-nella prossima sezione), 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 per le risposte nella direzione opposta.
-
-In questo modo, prima che venga creata una nuova connessione, il protocollo
-TCP si assicura che tutti gli eventuali segmenti residui di una precedente
-connessione, che potrebbero causare disturbi, siano stati eliminati dalla
-rete.
-
-
-\subsection{I numeri di porta}
-\label{sec:TCP_port_num}
-
-In un ambiente multitasking in un dato momento più processi devono poter 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
-\secref{sec:sock_sa_ipv4} e \secref{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 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'\href{http://www.ietf.org/rfc/rfc1700.txt}{RFC~1700} che contiene
-l'elenco delle porte assegnate dalla IANA (la \textit{Internet Assigned Number
- Authority}) ma l'elenco viene costantemente aggiornato e pubblicato su
-internet (una versione aggiornata si può trovare all'indirizzo
-\texttt{ftp://ftp.isi.edu/in-notes/iana/assignements/port-numbers}); inoltre
-in un sistema unix-like un analogo elenco viene mantenuto nel file
-\file{/etc/services}, con la corrispondenza fra i vari 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'\href{http://www.ietf.org/rfc/rfc1700.txt}{RFC~1700} i vari sistemi hanno
-fatto scelte diverse per le porte effimere, in particolare in
-\figref{fig:TCP_port_alloc} sono riportate quelle di BSD e Linux. Nel caso di
-Linux poi la scelta fra i due intervalli possibili viene fatta dinamicamente a
-seconda della memoria a disposizione del kernel per gestire le relative
-tabelle.
-
-\begin{figure}[!htb]
- \centering
- \includegraphics[width=15cm]{img/port_alloc}
- \caption{Allocazione dei numeri di porta.}
- \label{fig:TCP_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 amministratore, per far si che
-solo l'amministratore possa allocare queste porte per far partire i relativi
-servizi.
-
-Si tenga conto poi che ci sono alcuni client, in particolare \cmd{rsh} e
-\cmd{rlogin}, che richiedono una connessione su una porta riservata anche dal
-lato client come parte dell'autenticazione, contando appunto sul fatto che
-solo l'amministratore può usare queste porte. Data l'assoluta inconsistenza in
-termini di sicurezza di un tale metodo, al giorno d'oggi esso è in completo
-disuso.
-
-Data una connessione TCP si suole chiamare \textit{socket pair}\footnote{da
- non confondere con la coppia di socket della omonima funzione
- \func{socketpair} che fanno riferimento ad una coppia di socket sulla stessa
- macchina, non ai capi di una connessione TCP.} 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
-(\texttt{195.110.112.152:22}, \texttt{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 \cmd{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:TCP_port_cliserv}
-
-Per capire meglio l'uso delle porte e come vengono utilizzate quando si ha a
-che fare con un'applicazione client/server (come quelle che descriveremo in
-\secref{sec:TCP_daytime_application} e \secref{sec:TCP_echo_application})
-esamineremo cosa accade con le connessioni nel caso di un server TCP che deve
-gestire connessioni multiple.
-
-Se eseguiamo un \cmd{netstat} su una macchina di prova (il cui indirizzo sia
-\texttt{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 e attivi 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 interfacce locali. La notazione \texttt{0.0.0.0} usata da
-\cmd{netstat} è equivalente all'asterisco utilizzato per il numero di porta,
-indica il valore generico, e corrisponde al valore \const{INADDR\_ANY}
-definito in \file{arpa/inet.h} (vedi \ref{tab:TCP_ipv4_addr}).
-
-Inoltre si noti come la porta e l'indirizzo di ogni eventuale connessione
-esterna non sono specificati; in questo caso la \textit{socket pair} associata
-al socket potrebbe essere indicata come (\texttt{*:22}, \texttt{*:*}), usando
-anche per gli indirizzi l'asterisco come carattere che indica il valore
-generico.
-
-Dato che in genere una macchina è associata ad un solo indirizzo IP, ci si può
-chiedere che senso abbia l'utilizzo dell'indirizzo generico per specificare
-l'indirizzo locale; ma a parte il caso di macchine che hanno più di un
-indirizzo IP (il cosiddetto \textit{multihoming}) esiste sempre anche
-l'indirizzo di loopback, per cui con l'uso dell'indirizzo generico si possono
-accettare connessioni indirizzate verso uno qualunque degli indirizzi IP
-presenti. Ma, come si può vedere nell'esempio con il DNS che è in ascolto
-sulla porta 53, è possibile anche restringere l'accesso ad 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, per esempio
-quella con l'indirizzo \texttt{192.84.146.100}, si dovrà lanciare su
-quest'ultima un client \cmd{ssh} per creare una connessione, e il kernel gli
-assocerà una porta effimera (ad esempio la 21100), per cui la connessione sarà
-espressa dalla socket pair (\texttt{192.84.146.100:21100},
-\texttt{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 \cmd{netstat} otteniamo 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 utilizza anch'esso
-la porta 22, ed ha specificato l'indirizzo locale, questo è il socket con cui
-il processo figlio gestisce la connessione mentre il padre resta in ascolto
-sul socket originale.
-
-Se a questo punto lanciamo un'altra volta il client \cmd{ssh} per una seconda
-connessione quello che otterremo usando \cmd{netstat} 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è il client effettuerà la connessione usando un'altra porta effimera: con
-questa sarà aperta la connessione, ed il server creerà un'altro processo
-figlio per gestirla.
-
-Tutto ciò mostra come il TCP, per poter gestire le connessioni con un server
-concorrente, 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\footnote{ad esempio con il comando \cmd{fuser}, o con \cmd{lsof}.} 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{Le funzioni di base per la gestione dei socket}
-\label{sec:TCP_functions}
-
-In questa sezione descriveremo in maggior dettaglio le varie funzioni che
-vengono usate per la gestione di base dei socket TCP, non torneremo però sulla
-funzione \func{socket}, che è già stata esaminata accuratamente nel capitolo
-precedente in \secref{sec:sock_socket}.
-
-
-\subsection{La funzione \func{bind}}
-\label{sec:TCP_func_bind}
-
-La funzione \funcd{bind} assegna un indirizzo locale ad un socket. È usata
-cioè per specificare la prima parte dalla socket pair. Viene usata sul lato
-server per specificare la porta (e gli eventuali indirizzi locali) su cui poi
-ci si porrà in ascolto. Il prototipo della funzione è il seguente:
-\begin{prototype}{sys/socket.h}
-{int bind(int sockfd, const struct sockaddr *serv\_addr, socklen\_t addrlen)}
-
- Assegna un indirizzo ad un socket.
-
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore;
- in caso di errore la variabile \var{errno} viene impostata secondo i
- seguenti codici di errore:
- \begin{errlist}
- \item[\errcode{EBADF}] il file descriptor non è valido.
- \item[\errcode{EINVAL}] il socket ha già un indirizzo assegnato.
- \item[\errcode{ENOTSOCK}] il file descriptor non è associato ad un socket.
- \item[\errcode{EACCES}] si è cercato di usare una porta riservata senza
- sufficienti privilegi.
- \item[\errcode{EADDRNOTAVAIL}] Il tipo di indirizzo specificato non è
- disponibile.
- \item[\errcode{EADDRINUSE}] qualche altro socket sta già usando l'indirizzo.
- \end{errlist}
- ed anche \errval{EFAULT} e per i socket di tipo \const{AF\_UNIX},
- \errval{ENOTDIR}, \errval{ENOENT}, \errval{ENOMEM}, \errval{ELOOP},
- \errval{ENOSR} e \errval{EROFS}.}
-\end{prototype}
-
-Il primo argomento è un file descriptor ottenuto da una precedente chiamata a
-\func{socket}, mentre il secondo e terzo argomento sono rispettivamente
-l'indirizzo (locale) del socket e la dimensione della struttura che lo
-contiene, secondo quanto già trattato in \secref{sec:sock_sockaddr}.
-
-Con i socket TCP la chiamata \func{bind} permette di specificare l'indirizzo,
-la porta, entrambi o nessuno dei due. In genere i server utilizzano una porta
-nota che assegnano all'avvio, se questo non viene fatto è il kernel a
-scegliere una porta effimera quando vengono eseguite la funzioni
-\func{connect} o \func{listen}, ma se questo è normale per il client non lo è
-per il server\footnote{un'eccezione a tutto ciò sono i server che usano RPC.
- In questo caso viene fatta assegnare dal kernel una porta effimera che poi
- viene registrata presso il \textit{portmapper}; quest'ultimo è un altro
- demone che deve essere contattato dai client per ottenere la porta effimera
- su cui si trova il server.} che in genere viene identificato dalla porta su
-cui risponde (l'elenco di queste porte, e dei relativi servizi, è in
-\file{/etc/services}).
-
-Con \func{bind} si può assegnare un IP specifico ad un socket, purché questo
-appartenga ad una interfaccia della macchina. Per un client TCP questo
-diventerà l'indirizzo sorgente usato per i tutti i pacchetti inviati sul
-socket, mentre per un server TCP questo restringerà l'accesso al socket solo
-alle connessioni che arrivano verso tale indirizzo.
-
-Normalmente un client non specifica mai l'indirizzo di un socket, ed il kernel
-sceglie l'indirizzo di origine quando viene effettuata la connessione, sulla
-base dell'interfaccia usata per trasmettere i pacchetti, (che dipenderà dalle
-regole di instradamento usate per raggiungere il server). Se un server non
-specifica il suo indirizzo locale il kernel userà come indirizzo di origine
-l'indirizzo di destinazione specificato dal SYN del client.
-
-Per specificare un indirizzo generico, con IPv4 si usa il valore
-\const{INADDR\_ANY}, il cui valore, come accennato in
-\secref{sec:sock_sa_ipv4}, è pari a zero; nell'esempio
-\figref{fig:TCP_daytime_iter_server_code} si è usata un'assegnazione immediata
-del tipo: \includecodesnip{listati/serv_addr_sin_addr.c}
-
-Si noti che si è usato \func{htonl} per assegnare il valore
-\const{INADDR\_ANY}, anche se, essendo questo nullo, il riordinamento è
-inutile. Si tenga presente comunque che tutte le costanti \val{INADDR\_}
-(riportate in \tabref{tab:TCP_ipv4_addr}) sono definite secondo
-l'\textit{endianess} della macchina, ed anche se esse possono essere
-invarianti rispetto all'ordinamento dei bit, è comunque buona norma usare
-sempre la funzione \func{htonl}.
-
-\begin{table}[htb]
- \centering
- \footnotesize
- \begin{tabular}[c]{|l|l|}
- \hline
- \textbf{Costante} & \textbf{Significato} \\
- \hline
- \hline
- \const{INADDR\_ANY} & Indirizzo generico (\texttt{0.0.0.0})\\
- \const{INADDR\_BROADCAST}& Indirizzo di \textit{broadcast}.\\
- \const{INADDR\_LOOPBACK} & Indirizzo di \textit{loopback}
- (\texttt{127.0.0.1}).\\
- \const{INADDR\_NONE} & Indirizzo errato.\\
- \hline
- \end{tabular}
- \caption{Costanti di definizione di alcuni indirizzi generici per IPv4.}
- \label{tab:TCP_ipv4_addr}
-\end{table}
-
-L'esempio precedente funziona correttamente con IPv4 poiché che l'indirizzo è
-rappresentabile anche con un intero a 32 bit; non si può usare lo stesso
-metodo con IPv6, in cui l'indirizzo deve necessariamente essere specificato
-con una struttura, perché il linguaggio C non consente l'uso di una struttura
-costante come operando a destra in una assegnazione.
-
-Per questo motivo nell'header \file{netinet/in.h} è definita una variabile
-\const{in6addr\_any} (dichiarata come \direct{extern}, ed inizializzata dal
-sistema al valore \const{IN6ADRR\_ANY\_INIT}) che permette di effettuare una
-assegnazione del tipo: \includecodesnip{listati/serv_addr_sin6_addr.c} in
-maniera analoga si può utilizzare la variabile \const{in6addr\_loopback} per
-indicare l'indirizzo di \textit{loopback}, che a sua volta viene inizializzata
-staticamente a \const{IN6ADRR\_LOOPBACK\_INIT}.
-
-
-
-\subsection{La funzione \func{connect}}
-\label{sec:TCP_func_connect}
-
-La funzione \funcd{connect} è usata da un client TCP per stabilire la
-connessione con un server TCP, il prototipo della funzione è il seguente:
-\begin{prototype}{sys/socket.h}
-{int connect(int sockfd, const struct sockaddr *servaddr, socklen\_t addrlen)}
-
- Stabilisce una connessione fra due socket.
-
- \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
- errore, nel qual caso \var{errno} assumerà i valori:
- \begin{errlist}
- \item[\errcode{ECONNREFUSED}] non c'è nessuno in ascolto sull'indirizzo
- remoto.
- \item[\errcode{ETIMEDOUT}] si è avuto timeout durante il tentativo di
- connessione.
- \item[\errcode{ENETUNREACH}] la rete non è raggiungibile.
- \item[\errcode{EINPROGRESS}] il socket è non bloccante (vedi
- \secref{sec:file_noblocking}) e la connessione non può essere conclusa
- immediatamente.
- \item[\errcode{EALREADY}] il socket è non bloccante (vedi
- \secref{sec:file_noblocking}) e un tentativo precedente di connessione non
- si è ancora concluso.
- \item[\errcode{EAGAIN}] non ci sono più porte locali libere.
- \item[\errcode{EAFNOSUPPORT}] l'indirizzo non ha una famiglia di indirizzi
- corretta nel relativo campo.
- \item[\errcode{EACCES}, \errcode{EPERM}] si è tentato di eseguire una
- connessione ad un indirizzo broadcast senza che il socket fosse stato
- abilitato per il broadcast.
- \end{errlist}
- altri errori possibili sono: \errval{EFAULT}, \errval{EBADF},
- \errval{ENOTSOCK}, \errval{EISCONN} e \errval{EADDRINUSE}.}
-\end{prototype}
-
-Il primo argomento è un file descriptor ottenuto da una precedente chiamata a
-\func{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 \secref{sec:sock_sockaddr}.
-
-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 \secref{sec:TCP_daytime_client}, usando le funzioni illustrate in
-\secref{sec:sock_addr_func}.
-
-Nel caso di socket TCP la funzione \func{connect} avvia il \textit{three way
- handshake}, e ritorna solo quando la connessione è stabilita o si è
-verificato un errore. Le possibili cause di errore sono molteplici (ed i
-relativi codici riportati sopra), quelle che però dipendono dalla situazione
-della rete e non da errori o problemi nella chiamata della funzione sono le
-seguenti:
-\begin{enumerate}
-\item Il client non riceve risposta al SYN: l'errore restituito è
- \errcode{ETIMEDOUT}. Stevens riporta che BSD invia un primo SYN alla chiamata
- di \func{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
- \func{sysctl} che attraverso il filesystem \file{/proc} scrivendo il valore
- voluto in \file{/proc/sys/net/ipv4/tcp\_syn\_retries}. Il valore predefinito
- per la ripetizione dell'invio è di 5 volte, che comporta un timeout dopo
- circa 180 secondi.
-%
-% Le informazioni su tutte le opzioni impostabili via /proc stanno in
-% Linux/Documentation/networking/ip-sysctl.txt
-%
-\item 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 probabilmente 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
- \errcode{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, quando 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. In questo caso dato che il messaggio può
- essere dovuto ad una condizione transitoria si ripete l'emissione dei SYN
- come nel caso precedente, fino al timeout, e solo allora si restituisce il
- codice di errore dovuto al messaggio ICMP, che da luogo ad un
- \errcode{ENETUNREACH}.
-
-\end{enumerate}
-
-Se si fa riferimento al diagramma degli stati del TCP riportato in
-\figref{fig:TCP_state_diag} la funzione \func{connect} porta un socket
-dallo stato \texttt{CLOSED} (lo stato iniziale in cui si trova un socket
-appena creato) prima allo stato \texttt{SYN\_SENT} e poi, al ricevimento del
-ACK, nello stato \texttt{ESTABLISHED}. Se invece la connessione fallisce il
-socket non è più utilizzabile e deve essere chiuso.
-
-Si noti infine che con la funzione \func{connect} si è specificato solo
-indirizzo e porta del server, quindi solo una metà della socket pair; essendo
-questa funzione usata nei client l'altra metà contenente indirizzo e porta
-locale viene lasciata all'assegnazione automatica del kernel, e non è
-necessario effettuare una \func{bind}.
-
-
-\subsection{La funzione \func{listen}}
-\label{sec:TCP_func_listen}
-
-La funzione \funcd{listen} serve ad usare un socket in modalità passiva, cioè,
-come dice il nome, per metterlo in ascolto di eventuali connessioni; in
-sostanza l'effetto della funzione è di portare il socket dallo stato
-\texttt{CLOSED} a quello \texttt{LISTEN}. In genere si chiama la funzione in
-un server dopo le chiamate a \func{socket} e \func{bind} e prima della
-chiamata ad \func{accept}. Il prototipo della funzione, come definito dalla
-pagina di manuale, è:
-\begin{prototype}{sys/socket.h}{int listen(int sockfd, int backlog)}
- Pone un socket in attesa di una connessione.
-
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
- errore. I codici di errore restituiti in \var{errno} sono i seguenti:
- \begin{errlist}
- \item[\errcode{EBADF}] l'argomento \param{sockfd} non è un file descriptor
- valido.
- \item[\errcode{ENOTSOCK}] l'argomento \param{sockfd} non è un socket.
- \item[\errcode{EOPNOTSUPP}] il socket è di un tipo che non supporta questa
- operazione.
- \end{errlist}}
-\end{prototype}
-
-La funzione pone il socket specificato da \param{sockfd} in modalità passiva e
-predispone una coda per le connessioni in arrivo di lunghezza pari a
-\param{backlog}. La funzione si può applicare solo a socket di tipo
-\const{SOCK\_STREAM} o \const{SOCK\_SEQPACKET}.
-
-L'argomento \param{backlog} indica il numero massimo di connessioni pendenti
-accettate; se esso viene ecceduto il client al momento della richiesta della
-connessione riceverà un errore di tipo \errcode{ECONNREFUSED}, o se il
-protocollo, come accade nel caso del TCP, supporta la ritrasmissione, la
-richiesta sarà ignorata in modo che la connessione possa venire ritentata.
-
-Per capire meglio il significato di tutto ciò occorre approfondire la modalità
-con cui il kernel tratta le connessioni in arrivo. Per ogni socket in ascolto
-infatti vengono mantenute due code:
-\begin{enumerate}
-\item La coda delle connessioni incomplete (\textit{incomplete connection
- queue} che contiene un riferimento per ciascun socket per il quale è
- arrivato un SYN ma il \textit{three way handshake} non si è ancora concluso.
- Questi socket sono tutti nello stato \texttt{SYN\_RECV}.
-\item La coda delle connessioni complete (\textit{complete connection queue}
- che contiene un ingresso per ciascun socket per il quale il three way
- handshake è stato completato ma ancora \func{accept} non è ritornata.
- Questi socket sono tutti nello stato \texttt{ESTABLISHED}.
-\end{enumerate}
-
-Lo schema di funzionamento è descritto in \figref{fig:TCP_listen_backlog}:
-quando arriva un SYN da un client il server crea una nuova voce nella coda
-delle connessioni incomplete, e poi risponde con il SYN$+$ACK. La voce resterà
-nella coda delle connessioni incomplete fino al ricevimento dell'ACK dal
-client o fino ad un timeout. Nel caso di completamento del three way handshake
-la voce viene spostata nella coda delle connessioni complete. Quando il
-processo chiama la funzione \func{accept} (vedi \secref{sec:TCP_func_accept})
-la prima voce nella coda delle connessioni complete è passata al programma, o,
-se la coda è vuota, il processo viene posto in attesa e risvegliato all'arrivo
-della prima connessione completa.
-
-\begin{figure}[htb]
- \centering
- \includegraphics[width=11cm]{img/tcp_listen_backlog}
- \caption{Schema di funzionamento delle code delle connessioni complete ed
- incomplete.}
- \label{fig:TCP_listen_backlog}
-\end{figure}
-
-Storicamente il valore del parametro \param{backlog} era corrispondente al
-massimo valore della somma del numero di voci possibili per ciascuna delle due
-code. Stevens in \cite{UNP1} riporta che BSD ha sempre applicato un fattore di
-1.5 a detto valore, e fornisce una tabella con i risultati ottenuti con vari
-kernel, compreso Linux 2.0, che mostrano le differenze fra diverse
-implementazioni.
-
-In Linux il significato di questo valore è cambiato a partire dal kernel 2.2
-per prevenire l'attacco chiamato \textit{syn flood}. Questo si basa
-sull'emissione da parte dell'attaccante di un grande numero di pacchetti SYN
-indirizzati verso una porta, forgiati con indirizzo IP fasullo\footnote{con la
- tecnica che viene detta \textit{ip spoofing}.} così che i SYN$+$ACK vanno
-perduti e la coda delle connessioni incomplete viene saturata, impedendo di
-fatto ulteriori connessioni.
-
-Per ovviare a questo il significato del \param{backlog} è stato cambiato a
-indicare la lunghezza della coda delle connessioni complete. La lunghezza
-della coda delle connessioni incomplete può essere ancora controllata usando
-la funzione \func{sysctl} con il parametro \const{NET\_TCP\_MAX\_SYN\_BACKLOG}
-o scrivendola direttamente in
-\file{/proc/sys/net/ipv4/tcp\_max\_syn\_backlog}. Quando si attiva la
-protezione dei syncookies però (con l'opzione da compilare nel kernel e da
-attivare usando \file{/proc/sys/net/ipv4/tcp\_syncookies}) questo valore viene
-ignorato e non esiste più un valore massimo. In ogni caso in Linux il valore
-di \param{backlog} viene troncato ad un massimo di \const{SOMAXCONN} se è
-superiore a detta costante (che di default vale 128).
-
-La scelta storica per il valore di questo parametro era di 5, e alcuni vecchi
-kernel non supportavano neanche valori superiori, ma la situazione corrente è
-molto cambiata per via della presenza di server web che devono gestire un gran
-numero di connessioni per cui un tale valore non è più adeguato. Non esiste
-comunque una risposta univoca per la scelta del valore, per questo non
-conviene specificarlo con una costante (il cui cambiamento richiederebbe la
-ricompilazione del server) ma usare piuttosto una variabile di ambiente (vedi
-\secref{sec:proc_environ}).
-
-Stevens tratta accuratamente questo argomento in \cite{UNP1}, con esempi presi
-da casi reali su web server, ed in particolare evidenzia come non sia più vero
-che il compito principale della coda sia quello di gestire il caso in cui il
-server è occupato fra chiamate successive alla \func{accept} (per cui la coda
-più occupata sarebbe quella delle connessioni completate), ma piuttosto quello
-di gestire la presenza di un gran numero di SYN in attesa di concludere il
-three way handshake.
-
-Infine va messo in evidenza che, nel caso di socket TCP, quando un SYN arriva
-con tutte le code piene, il pacchetto deve essere ignorato. Questo perché la
-condizione in cui le code sono piene è ovviamente transitoria, per cui se il
-client ritrasmette il SYN è probabile che passato un po' di tempo possa
-trovare nella coda lo spazio per una nuova connessione. Se invece si
-rispondesse con un RST, per indicare l'impossibilità di effettuare la
-connessione, la chiamata a \func{connect} nel client ritornerebbe con una
-condizione di errore, costringendo a inserire nell'applicazione la gestione
-dei tentativi di riconnessione, che invece può essere effettuata in maniera
-trasparente dal protocollo TCP.
-
-
-\subsection{La funzione \func{accept}}
-\label{sec:TCP_func_accept}
-
-La funzione \funcd{accept} è chiamata da un server per gestire la connessione
-una volta che sia stato completato il \textit{three way handshake}, la
-funzione restituisce un nuovo socket descriptor su cui si potrà operare per
-effettuare la comunicazione. Se non ci sono connessioni completate il processo
-viene messo in attesa. Il prototipo della funzione è il seguente:
-\begin{prototype}{sys/socket.h}
-{int accept(int sockfd, struct sockaddr *addr, socklen\_t *addrlen)}
-
- Accetta una connessione sul socket specificato.
-
- \bodydesc{La funzione restituisce un numero di socket descriptor positivo in
- caso di successo e -1 in caso di errore, nel qual caso \var{errno} viene
- impostata ai seguenti valori:
-
- \begin{errlist}
- \item[\errcode{EBADF}] l'argomento \param{sockfd} non è un file descriptor
- valido.
- \item[\errcode{ENOTSOCK}] l'argomento \param{sockfd} non è un socket.
- \item[\errcode{EOPNOTSUPP}] il socket è di un tipo che non supporta questa
- operazione.
- \item[\errcode{EAGAIN} o \errcode{EWOULDBLOCK}] il socket è stato impostato
- come non bloccante (vedi \secref{sec:file_noblocking}), e non ci sono
- connessioni in attesa di essere accettate.
- \item[\errcode{EPERM}] Le regole del firewall non consentono la connessione.
- \item[\errcode{ENOBUFS}, \errcode{ENOMEM}] questo spesso significa che
- l'allocazione della memoria è limitata dai limiti sui buffer dei socket,
- non dalla memoria di sistema.
- \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
- \end{errlist}
- Inoltre possono essere restituiti gli errori di rete relativi al nuovo
- socket, diversi a secondo del protocollo, come: \errval{EMFILE},
- \errval{EINVAL}, \errval{ENOSR}, \errval{ENOBUFS}, \errval{EFAULT},
- \errval{EPERM}, \errval{ECONNABORTED}, \errval{ESOCKTNOSUPPORT},
- \errval{EPROTONOSUPPORT}, \errval{ETIMEDOUT}, \errval{ERESTARTSYS}.}
-\end{prototype}
-
-La funzione estrae la prima connessione relativa al socket \param{sockfd} in
-attesa sulla coda delle connessioni complete, che associa ad nuovo socket con
-le stesse caratteristiche di \param{sockfd}. Il socket originale non viene
-toccato e resta nello stato di \texttt{LISTEN}, mentre il nuovo socket viene
-posto nello stato \texttt{ESTABLISHED}. Nella struttura \param{addr} e nella
-variabile \param{addrlen} vengono restituiti indirizzo e relativa lunghezza
-del client che si è connesso.
-
-I due argomenti \param{addr} e \param{addrlen} (si noti che quest'ultimo è
-passato per indirizzo per avere indietro il valore) sono usati per ottenere
-l'indirizzo del client da cui proviene la connessione. Prima della chiamata
-\param{addrlen} deve essere inizializzato alle dimensioni della struttura il
-cui indirizzo è passato come argomento in \param{addr}; al ritorno della
-funzione \param{addrlen} conterrà il numero di byte scritti dentro
-\param{addr}. Se questa informazione non interessa basterà inizializzare a
-\val{NULL} detti puntatori.
-
-Se la funzione ha successo restituisce il descrittore di un nuovo socket
-creato dal kernel (detto \textit{connected socket}) a cui viene associata la
-prima connessione completa (estratta dalla relativa coda, vedi
-\secref{sec:TCP_func_listen}) che il client ha effettuato verso il socket
-\param{sockfd}. Quest'ultimo (detto \textit{listening socket}) è quello creato
-all'inizio e messo in ascolto con \func{listen}, e non viene toccato dalla
-funzione. Se non ci sono connessioni pendenti da accettare la funzione mette
-in attesa il processo\footnote{a meno che non si sia impostato il socket per
- essere non bloccante (vedi \secref{sec:file_noblocking}), nel qual caso
- ritorna con l'errore \errcode{EAGAIN}. Torneremo su questa modalità di
- operazione in \secref{sec:xxx_sock_noblock}.} fintanto che non ne arriva
-una.
-
-La funzione può essere usata solo con socket che supportino la connessione
-(cioè di tipo \const{SOCK\_STREAM}, \const{SOCK\_SEQPACKET} o
-\const{SOCK\_RDM}). Per alcuni protocolli che richiedono una conferma
-esplicita della connessione,\footnote{attualmente in Linux solo DECnet ha
- questo comportamento.} la funzione opera solo l'estrazione dalla coda delle
-connessioni, la conferma della connessione viene eseguita implicitamente dalla
-prima chiamata ad una \func{read} o una \func{write}, mentre il rifiuto della
-connessione viene eseguito con la funzione \func{close}.
-
-È da chiarire che Linux presenta un comportamento diverso nella gestione degli
-errori rispetto ad altre implementazioni dei socket BSD, infatti la funzione
-\func{accept} passa gli errori di rete pendenti sul nuovo socket come codici
-di errore per \func{accept}, per cui l'applicazione deve tenerne conto ed
-eventualmente ripetere la chiamata alla funzione come per l'errore di
-\errcode{EAGAIN} (torneremo su questo in \secref{sec:TCP_echo_critical}).
-Un'altra differenza con BSD è che la funzione non fa ereditare al nuovo socket
-i flag del socket originale, come \const{O\_NONBLOCK},\footnote{ed in generale
- tutti quelli che si possono impostare con \func{fcntl}, vedi
- \secref{sec:file_fcntl}.} che devono essere rispecificati ogni volta. Tutto
-questo deve essere tenuto in conto se si devono scrivere programmi portabili.
-
-Il meccanismo di funzionamento di \func{accept} è essenziale per capire il
-funzionamento di un server: in generale infatti c'è sempre un solo socket in
-ascolto, detto per questo \textit{listening socket}, che resta per tutto il
-tempo nello stato \texttt{LISTEN}, mentre le connessioni vengono gestite dai
-nuovi socket, detti \textit{connected socket}, ritornati da \func{accept}, che
-si trovano automaticamente nello stato \texttt{ESTABLISHED}, e vengono
-utilizzati per lo scambio dei dati, che avviene su di essi, fino alla chiusura
-della connessione. Si può riconoscere questo schema anche nell'esempio
-elementare di \figref{fig:TCP_daytime_iter_server_code}, dove per ogni
-connessione il socket creato da \func{accept} viene chiuso dopo l'invio dei
-dati.
-
-
-\subsection{Le funzioni \func{getsockname} e \func{getpeername}}
-\label{sec:TCP_get_names}
-
-Oltre a tutte quelle viste finora, dedicate all'utilizzo dei socket, esistono
-alcune funzioni ausiliarie che possono essere usate per recuperare alcune
-informazioni relative ai socket ed alle connessioni ad essi associate. Le due
-funzioni più elementari sono queste, che vengono usate per ottenere i dati
-relativi alla socket pair associata ad un certo socket.
-
-La prima funzione è \funcd{getsockname} e serve ad ottenere l'indirizzo locale
-associato ad un socket; il suo prototipo è:
-\begin{prototype}{sys/socket.h}
- {int getsockname(int sockfd, struct sockaddr * name, socklen\_t * namelen)}
- Legge l'indirizzo locale di un socket.
-
-\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
- errore. I codici di errore restituiti in \var{errno} sono i seguenti:
- \begin{errlist}
- \item[\errcode{EBADF}] l'argomento \param{sockfd} non è un file descriptor
- valido.
- \item[\errcode{ENOTSOCK}] l'argomento \param{sockfd} non è un socket.
- \item[\errcode{ENOBUFS}] non ci sono risorse sufficienti nel sistema per
- eseguire l'operazione.
- \item[\errcode{EFAULT}] l'indirizzo \param{name} non è valido.
- \end{errlist}}
-\end{prototype}
-
-La funzione restituisce la struttura degli indirizzi del socket \param{sockfd}
-nella struttura indicata dal puntatore \param{name} la cui lunghezza è
-specificata tramite l'argomento \param{namlen}. Quest'ultimo viene passato
-come indirizzo per avere indietro anche il numero di byte effettivamente
-scritti nella struttura puntata da \param{name}. Si tenga presente che se si è
-utilizzato un buffer troppo piccolo per \param{name} l'indirizzo risulterà
-troncato.
-
-La funzione si usa tutte le volte che si vuole avere l'indirizzo locale di un
-socket; ad esempio può essere usata da un client (che usualmente non chiama
-\func{bind}) per ottenere numero IP e porta locale associati al socket
-restituito da una \func{connect}, o da un server che ha chiamato \func{bind}
-su un socket usando 0 come porta locale per ottenere il numero di porta
-effimera assegnato dal kernel.
-
-Inoltre quando un server esegue una \func{bind} su un indirizzo generico, se
-chiamata dopo il completamento di una connessione sul socket restituito da
-\func{accept}, restituisce l'indirizzo locale che il kernel ha assegnato a
-quella connessione.
-
-Tutte le volte che si vuole avere l'indirizzo remoto di un socket si usa la
-funzione \funcd{getpeername}, il cui prototipo è:
-\begin{prototype}{sys/socket.h}
- {int getpeername(int sockfd, struct sockaddr * name, socklen\_t * namelen)}
- Legge l'indirizzo remoto di un socket.
-
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
- errore. I codici di errore restituiti in \var{errno} sono i seguenti:
- \begin{errlist}
- \item[\errcode{EBADF}] l'argomento \param{sockfd} non è un file descriptor
- valido.
- \item[\errcode{ENOTSOCK}] l'argomento \param{sockfd} non è un socket.
- \item[\errcode{ENOTCONN}] il socket non è connesso.
- \item[\errcode{ENOBUFS}] non ci sono risorse sufficienti nel sistema per
- eseguire l'operazione.
- \item[\errcode{EFAULT}] l'argomento \param{name} punta al di fuori dello
- spazio di indirizzi del processo.
- \end{errlist}}
-\end{prototype}
-
-La funzione è identica a \func{getsockname}, ed usa la stessa sintassi, ma
-restituisce l'indirizzo remoto del socket, cioè quello associato all'altro
-capo della connessione. Ci si può chiedere a cosa serva questa funzione dato
-che dal lato client l'indirizzo remoto è sempre noto quando si esegue la
-\func{connect} mentre dal lato server si possono usare, come vedremo in
-\figref{fig:TCP_daytime_cunc_server_code}, i valori di ritorno di
-\func{accept}.
-
-Il fatto è che in generale quest'ultimo caso non è sempre possibile. In
-particolare questo avviene quando il server, invece di gestire la connessione
-direttamente in un processo figlio, come vedremo nell'esempio di server
-concorrente di \secref{sec:TCP_daytime_cunc_server}, lancia per ciascuna
-connessione un altro programma, usando \func{exec}.\footnote{questa ad esempio
- è la modalità con cui opera il \textsl{super-server} \cmd{inetd}, che può
- gestire tutta una serie di servizi diversi, eseguendo su ogni connessione
- ricevuta sulle porte tenute sotto controllo, il relativo server.}
-
-In questo caso benché il processo figlio abbia una immagine della memoria che
-è copia di quella del processo padre (e contiene quindi anche la struttura
-ritornata da \func{accept}), all'esecuzione di \func{exec} verrà caricata in
-memoria l'immagine del programma eseguito, che a questo punto perde ogni
-riferimento ai valori tornati da \func{accept}. Il socket descriptor però
-resta aperto, e se si è seguita una opportuna convenzione per rendere noto al
-programma eseguito qual'è il socket connesso, \footnote{ad esempio il solito
- \cmd{inetd} fa sempre in modo che i file descriptor 0, 1 e 2 corrispondano
- al socket connesso.} quest'ultimo potrà usare la funzione \func{getpeername}
-per determinare l'indirizzo remoto del client.
-
-Infine è da chiarire (si legga la pagina di manuale) che, come per
-\func{accept}, il terzo parametro, che è specificato dallo standard POSIX.1g
-come di tipo \code{socklen\_t *} in realtà deve sempre corrispondere ad un
-\ctyp{int *} come prima dello standard perché tutte le implementazioni dei
-socket BSD fanno questa assunzione.
-
-
-\subsection{La funzione \func{close}}
-\label{sec:TCP_func_close}
-
-La funzione standard Unix \func{close} (vedi \secref{sec:file_close}) che si
-usa sui file può essere usata con lo stesso effetto anche sui file descriptor
-associati ad un socket.
-
-L'azione di questa funzione quando applicata a socket è di marcarlo come
-chiuso e ritornare immediatamente al processo. Una volta chiamata il socket
-descriptor non è più utilizzabile dal processo e non può essere usato come
-argomento per una \func{write} o una \func{read} (anche se l'altro capo della
-connessione non avesse chiuso la sua parte). Il kernel invierà comunque tutti
-i dati che ha in coda prima di iniziare la sequenza di chiusura.
-
-Vedremo più avanti in \secref{sec:TCP_so_linger} come è possibile cambiare
-questo comportamento, e cosa deve essere fatto perché il processo possa
-assicurarsi che l'altro capo abbia ricevuto tutti i dati.
-
-Come per tutti i file descriptor anche per i socket viene mantenuto un numero
-di riferimenti, per cui se più di un processo ha lo stesso socket aperto
-l'emissione del FIN e la sequenza di chiusura di TCP non viene innescata
-fintanto che il numero di riferimenti non si annulla, questo si applica, come
-visto in \secref{sec:file_sharing}, sia ai file descriptor duplicati che a
-quelli ereditati dagli eventuali processi figli, ed è il comportamento che ci
-si aspetta in una qualunque applicazione client/server.
-
-Per attivare immediatamente l'emissione del FIN e la sequenza di chiusura
-descritta in \secref{sec:TCP_conn_term}, si può invece usare la funzione
-\func{shutdown} su cui torneremo in seguito (vedi \secref{sec:xxx_shutdown}).
-
-
-
-\section{Un esempio elementare: il servizio \textit{daytime}}
-\label{sec:TCP_daytime_application}
-
-Avendo introdotto le funzioni di base per la gestione dei socket, potremo
-vedere in questa sezione un primo esempio di applicazione elementare che
-implementa il servizio \textit{daytime} su TCP, secondo quanto specificato
-dall'\href{http://www.ietf.org/rfc/rfc0867.txt}{RFC~867}. Prima di passare
-agli esempi del client e del server, inizieremo riesaminando con maggiori
-dettagli una peculiarità delle funzioni di I/O, già accennata in
-\secref{sec:file_read} e \secref{sec:file_write}, che nel caso dei socket è
-particolarmente rilevante. Passeremo poi ad illustrare gli esempi
-dell'implementazione, sia dal lato client, che dal lato server, che si è
-realizzato sia in forma iterativa che concorrente.
-
-
-\subsection{Il comportamento delle funzioni di I/O}
-\label{sec:sock_io_behav}
-
-Una cosa che si tende a dimenticare quando si ha a che fare con i socket è che
-le funzioni di input/output non sempre hanno lo stesso comportamento che
-avrebbero con i normali file di dati (in particolare questo accade per i
-socket di tipo stream).
-
-Infatti con i socket è comune che funzioni come \func{read} o \func{write}
-possano restituire in input o scrivere in output un numero di byte minore di
-quello richiesto. Come già accennato in \secref{sec:file_read} questo è un
-comportamento normale per le funzioni di I/O, ma con i normali file di dati il
-problema si avverte solo in lettura, quando si incontra la fine del file. In
-generale non è così, e con i socket questo è particolarmente evidente.
-
-
-\begin{figure}[htb]
- \footnotesize \centering
- \begin{minipage}[c]{15cm}
- \includecodesample{listati/FullRead.c}
- \end{minipage}
- \normalsize
- \caption{La funzione \func{FullRead}, che legge esattamente \var{count} byte
- da un file descriptor, iterando opportunamente le letture.}
- \label{fig:sock_FullRead_code}
-\end{figure}
-
-Quando ci si trova ad affrontare questo comportamento tutto quello che si deve
-fare è semplicemente ripetere la lettura (o la scrittura) per la quantità di
-byte restanti, tenendo conto che le funzioni si possono bloccare se i dati non
-sono disponibili: è lo stesso comportamento che si può avere scrivendo più di
-\const{PIPE\_BUF} byte in una pipe (si riveda quanto detto in
-\secref{sec:ipc_pipes}).
-
-Per questo motivo, seguendo l'esempio di R. W. Stevens in \cite{UNP1}, si sono
-definite due funzioni, \func{FullRead} e \func{FullWrite}, che eseguono
-lettura e scrittura tenendo conto di questa caratteristica, ed in grado di
-ritornare solo dopo avere letto o scritto esattamente il numero di byte
-specificato; il sorgente è riportato rispettivamente in
-\figref{fig:sock_FullRead_code} e \figref{fig:sock_FullWrite_code} ed è
-disponibile fra i sorgenti allegati alla guida nei file \file{FullRead.c} e
-\file{FullWrite.c}.
-
-\begin{figure}[htb]
- \centering
- \footnotesize \centering
- \begin{minipage}[c]{15cm}
- \includecodesample{listati/FullWrite.c}
- \end{minipage}
- \normalsize
- \caption{La funzione \func{FullWrite}, che scrive esattamente \var{count}
- byte su un file descriptor, iterando opportunamente le scritture.}
- \label{fig:sock_FullWrite_code}
-\end{figure}
-
-Come si può notare le due funzioni ripetono la lettura/scrittura in un ciclo
-fino all'esaurimento del numero di byte richiesti, in caso di errore viene
-controllato se questo è \errcode{EINTR} (cioè un'interruzione della system
-call dovuta ad un segnale), nel qual caso l'accesso viene ripetuto, altrimenti
-l'errore viene ritornato al programma chiamante, interrompendo il ciclo.
-
-Nel caso della lettura, se il numero di byte letti è zero, significa che si è
-arrivati alla fine del file (per i socket questo significa in genere che
-l'altro capo è stato chiuso, e quindi non sarà più possibile leggere niente) e
-pertanto si ritorna senza aver concluso la lettura di tutti i byte
-richiesti. Entrambe le funzioni restituiscono 0 in caso di successo, ed un
-valore negativo in caso di errore, \texttt{FullRead} restituisce il numero di
-byte non letti in caso di end-of-file prematuro.
-
-
-\subsection{Il client \textit{daytime}}
-\label{sec:TCP_daytime_client}
-
-Il primo esempio di applicazione delle funzioni di base illustrate in
-\secref{sec:TCP_functions} è relativo alla creazione di un client elementare
-per il servizio \textit{daytime}, un servizio elementare, definito
-nell'\href{http://www.ietf.org/rfc/rfc0867.txt}{RFC~867}, che restituisce
-l'ora locale della macchina a cui si effettua la richiesta, e che è assegnato
-alla porta 13.
-
-In \figref{fig:TCP_daytime_client_code} è riportata la sezione principale del
-codice del nostro client. Il sorgente completo del programma
-(\file{TCP\_daytime.c}, che comprende il trattamento delle opzioni ed una
-funzione per stampare un messaggio di aiuto) è allegato alla guida nella
-sezione dei codici sorgente e può essere compilato su una qualunque macchina
-GNU/Linux.
-
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15cm}
- \includecodesample{listati/TCP_daytime.c}
- \end{minipage}
- \normalsize
- \caption{Esempio di codice di un client elementare per il servizio
- \textit{daytime}.}
- \label{fig:TCP_daytime_client_code}
-\end{figure}
-
-Il programma anzitutto (\texttt{\small 1--5}) include gli header necessari;
-dopo la dichiarazione delle variabili (\texttt{\small 9--12}) si è omessa
-tutta la parte relativa al trattamento degli argomenti passati dalla linea di
-comando (effettuata con le apposite funzioni illustrate in
-\secref{sec:proc_opt_handling}).
-
-Il primo passo (\texttt{\small 14--18}) è creare un socket TCP (quindi di tipo
-\const{SOCK\_STREAM} e di famiglia \const{AF\_INET}). La funzione
-\func{socket} ritorna il descrittore che viene usato per identificare il
-socket in tutte le chiamate successive. Nel caso la chiamata fallisca si
-stampa un errore (\texttt{\small 16}) con la funzione \func{perror} e si esce
-(\texttt{\small 17}) con un codice di errore.
-
-Il passo seguente (\texttt{\small 19--27}) è quello di costruire un'apposita
-struttura \struct{sockaddr\_in} in cui sarà inserito l'indirizzo del server ed
-il numero della porta del servizio. Il primo passo (\texttt{\small 20}) è
-inizializzare tutto a zero, per poi inserire il tipo di indirizzo
-(\texttt{\small 21}) e la porta (\texttt{\small 22}), usando per quest'ultima
-la funzione \func{htons} per convertire il formato dell'intero usato dal
-computer a quello usato nella rete, infine \texttt{\small 23--27} si può
-utilizzare la funzione \func{inet\_pton} per convertire l'indirizzo numerico
-passato dalla linea di comando.
-
-A questo punto (\texttt{\small 28--32}) usando la funzione \func{connect} sul
-socket creato in precedenza (\texttt{\small 29}) si può stabilire la
-connessione con il server. Per questo si deve utilizzare come secondo
-argomento la struttura preparata in precedenza con il relativo indirizzo; si
-noti come, esistendo diversi tipi di socket, si sia dovuto effettuare un cast.
-Un valore di ritorno della funzione negativo implica il fallimento della
-connessione, nel qual caso si stampa un errore (\texttt{\small 30}) e si
-ritorna (\texttt{\small 31}).
-
-Completata con successo la connessione il passo successivo (\texttt{\small
- 34--40}) è leggere la data dal socket; il protocollo prevede che il server
-invii sempre una stringa alfanumerica, il formato della stringa non è
-specificato dallo standard, per cui noi useremo il formato usato dalla
-funzione \func{ctime}, seguito dai caratteri di terminazione \verb|\r\n|, cioè
-qualcosa del tipo:
-\begin{verbatim}
-Wed Apr 4 00:53:00 2001\r\n
-\end{verbatim}
-questa viene letta dal socket (\texttt{\small 34}) con la funzione \func{read}
-in un buffer temporaneo; la stringa poi deve essere terminata (\texttt{\small
- 35}) con il solito carattere nullo per poter essere stampata (\texttt{\small
- 36}) sullo standard output con l'uso di \func{fputs}.
-
-Come si è già spiegato in \secref{sec:sock_io_behav} la risposta dal socket
-potrà arrivare in un unico pacchetto di 26 byte (come avverrà senz'altro nel
-caso in questione) ma potrebbe anche arrivare in 26 pacchetti di un byte. Per
-questo nel caso generale non si può mai assumere che tutti i dati arrivino con
-una singola lettura, pertanto quest'ultima deve essere effettuata in un ciclo
-in cui si continui a leggere fintanto che la funzione \func{read} non ritorni
-uno zero (che significa che l'altro capo ha chiuso la connessione) o un numero
-minore di zero (che significa un errore nella connessione).
-
-Si noti come in questo caso la fine dei dati sia specificata dal server che
-chiude la connessione (anche questo è quanto richiesto dal protocollo); questa
-è una delle tecniche possibili (è quella usata pure dal protocollo HTTP), ma
-ce ne possono essere altre, ad esempio FTP marca la conclusione di un blocco
-di dati con la sequenza ASCII \verb|\r\n| (carriage return e line feed),
-mentre il DNS mette la lunghezza in testa ad ogni blocco che trasmette. Il
-punto essenziale è che TCP non provvede nessuna indicazione che permetta di
-marcare dei blocchi di dati, per cui se questo è necessario deve provvedere il
-programma stesso.
-
-Se abilitiamo il servizio \textit{daytime}\footnote{in genere questo viene
- fornito direttamente dal \textsl{superdemone} \texttt{inetd}, pertanto basta
- assicurarsi che esso sia abilitato nel relativo file di configurazione.}
-possiamo verificare il funzionamento del nostro client, avremo allora:
-\begin{verbatim}
-[piccardi@gont sources]$ ./daytime 127.0.0.1
-Mon Apr 21 20:46:11 2003
-\end{verbatim}%$
-e come si vede tutto funziona regolarmente.
-
-
-\subsection{Un server \textit{daytime} iterativo}
-\label{sec:TCP_daytime_iter_server}
-
-Dopo aver illustrato il client daremo anche un esempio di un server
-elementare, che sia anche in grado di rispondere al precedente client. Come
-primo esempio realizzeremo un server iterativo, in grado di fornire una sola
-risposta alla volta. Il codice del programma è nuovamente mostrato in
-\figref{fig:TCP_daytime_iter_server_code}, il sorgente completo
-(\file{TCP\_iter\_daytimed.c}) è allegato insieme agli altri file degli esempi.
-
-\begin{figure}[!htbp]
- \footnotesize \centering
- \begin{minipage}[c]{15cm}
- \includecodesample{listati/TCP_iter_daytimed.c}
- \end{minipage}
- \normalsize
- \caption{Esempio di codice di un semplice server per il servizio daytime.}
- \label{fig:TCP_daytime_iter_server_code}
-\end{figure}
-
-Come per il client si includono (\texttt{\small 1--9}) gli header necessari a
-cui è aggiunto quello per trattare i tempi, e si definiscono (\texttt{\small
- 14--18}) alcune costanti e le variabili necessarie in seguito. Come nel caso
-precedente si sono omesse le parti relative al trattamento delle opzioni da
-riga di comando.
-
-La creazione del socket (\texttt{\small 20--24}) è analoga al caso precedente,
-come pure l'inizializzazione (\texttt{\small 25--29}) della struttura
-\struct{sockaddr\_in}. Anche in questo caso (\texttt{\small 28}) si usa la
-porta standard del servizio daytime, ma come indirizzo IP si usa
-(\texttt{\small 27}) il valore predefinito \const{INET\_ANY}, che corrisponde
-all'indirizzo generico.
-
-Si effettua poi (\texttt{\small 30--34}) la chiamata alla funzione \func{bind}
-che permette di associare la precedente struttura al socket, in modo che
-quest'ultimo possa essere usato per accettare connessioni su una qualunque
-delle interfacce di rete locali. In caso di errore si stampa (\texttt{\small
- 31}) un messaggio, e si termina (\texttt{\small 32}) immediatamente il
-programma.
-
-Il passo successivo (\texttt{\small 35--39}) è quello di mettere ``in
-ascolto'' il socket; questo viene fatto (\texttt{\small 36}) con la funzione
-\func{listen} che dice al kernel di accettare connessioni per il socket che
-abbiamo creato; la funzione indica inoltre, con il secondo parametro, il
-numero massimo di connessioni che il kernel accetterà di mettere in coda per
-il suddetto socket. Di nuovo in caso di errore si stampa (\texttt{\small 37})
-un messaggio, e si esce (\texttt{\small 38}) immediatamente.
-
-La chiamata a \func{listen} completa la preparazione del socket per l'ascolto
-(che viene chiamato anche \textit{listening descriptor}) a questo punto si può
-procedere con il ciclo principale (\texttt{\small 40--53}) che viene eseguito
-indefinitamente. Il primo passo (\texttt{\small 42}) è porsi in attesa di
-connessioni con la chiamata alla funzione \func{accept}, come in precedenza in
-caso di errore si stampa (\texttt{\small 43}) un messaggio, e si esce
-(\texttt{\small 44}).
-
-Il processo resterà in stato di \textit{sleep} fin quando non arriva e viene
-accettata una connessione da un client; quando questo avviene \func{accept}
-ritorna, restituendo un secondo descrittore, che viene chiamato
-\textit{connected descriptor}, e che è quello che verrà usato dalla successiva
-chiamata alla \func{write} per scrivere la risposta al client.
-
-Il ciclo quindi proseguirà determinando (\texttt{\small 46}) il tempo corrente
-con una chiamata a \texttt{time}, con il quale si potrà opportunamente
-costruire (\texttt{\small 47}) la stringa con la data da trasmettere
-(\texttt{\small 48}) con la chiamata a \func{write}. Completata la
-trasmissione il nuovo socket viene chiuso (\texttt{\small 52}). A questo
-punto il ciclo si chiude ricominciando da capo in modo da poter ripetere
-l'invio della data in risposta ad una successiva connessione.
-
-È importante notare che questo server è estremamente elementare, infatti, a
-parte il fatto di poter essere usato solo con indirizzi IPv4, esso è in grado
-di rispondere ad un solo un client alla volta: è cioè, come dicevamo, un
-\textsl{server iterativo}. Inoltre è scritto per essere lanciato da linea di
-comando, se lo si volesse utilizzare come demone occorrerebbero le opportune
-modifiche\footnote{come una chiamata a \func{daemon} prima dell'inizio del
- ciclo principale.} per tener conto di quanto illustrato in
-\secref{sec:sess_daemon}. Si noti anche che non si è inserita nessuna forma di
-gestione della terminazione del processo, dato che tutti i file descriptor
-vengono chiusi automaticamente alla sua uscita, e che, non generando figli,
-non è necessario preoccuparsi di gestire la loro terminazione.
-
-
-\subsection{Un server \textit{daytime} concorrente}
-\label{sec:TCP_daytime_cunc_server}
-
-Il server \texttt{daytime} dell'esempio in
-\secref{sec:TCP_daytime_iter_server} è un tipico esempio di server iterativo,
-in cui viene servita una richiesta alla volta; in generale però, specie se il
-servizio è più complesso e comporta uno scambio di dati più sostanzioso di
-quello in questione, non è opportuno bloccare un server nel servizio di un
-client per volta; per questo si ricorre alle capacità di multitasking del
-sistema.
-
-Come accennato anche in \secref{sec:proc_gen} una delle modalità più comuni di
-funzionamento da parte dei server è quella di usare la funzione \func{fork}
-per creare, ad ogni richiesta da parte di un client, un processo figlio che si
-incarichi della gestione della comunicazione. Si è allora riscritto il server
-\textit{daytime} dell'esempio precedente in forma concorrente, inserendo anche
-una opzione per la stampa degli indirizzi delle connessioni ricevute.
-
-In \figref{fig:TCP_daytime_cunc_server_code} è mostrato un estratto del
-codice, in cui si sono tralasciati il trattamento delle opzioni e le parti
-rimaste invariate rispetto al precedente esempio (cioè tutta la parte
-riguardante l'apertura passiva del socket). Al solito il sorgente completo del
-server, nel file \file{TCP\_cunc\_daytimed.c}, è allegato insieme ai sorgenti
-degli altri esempi.
-
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15cm}
- \includecodesample{listati/TCP_cunc_daytimed.c}
- \end{minipage}
- \normalsize
- \caption{Esempio di codice di un server concorrente elementare per il
- servizio daytime.}
- \label{fig:TCP_daytime_cunc_server_code}
-\end{figure}
-
-Stavolta (\texttt{\small 21--25}) la funzione \func{accept} è chiamata
-fornendo una struttura di indirizzi in cui saranno ritornati l'indirizzo IP e
-la porta da cui il client effettua la connessione, che in un secondo tempo,
-(\texttt{\small 39--43}), se il logging è abilitato, stamperemo sullo standard
-output.
-
-Quando \func{accept} ritorna il server chiama la funzione \func{fork}
-(\texttt{\small 26--30}) per creare il processo figlio che effettuerà
-(\texttt{\small 31--45}) tutte le operazioni relative a quella connessione,
-mentre il padre proseguirà l'esecuzione del ciclo principale in attesa di
-ulteriori connessioni.
-
-Si noti come il figlio operi solo sul socket connesso, chiudendo
-immediatamente (\texttt{\small 32}) il socket \var{list\_fd}; mentre il padre
-continua ad operare (\texttt{\small 47}) solo sul socket in ascolto chiudendo
-\var{sock\_fd} al ritorno dalla \func{fork}. Per quanto abbiamo detto in
-\secref{sec:TCP_func_close} nessuna delle due chiamate a \func{close} causa
-l'innesco della sequenza di chiusura perché il numero di riferimenti al file
-descriptor non si è annullato.
-
-Infatti subito dopo la creazione del socket \var{list\_fd} ha una referenza, e
-lo stesso vale per \var{sock\_fd} dopo il ritorno di \func{accept}, ma dopo la
-\func{fork} i descrittori vengono duplicati nel padre e nel figlio per cui
-entrambi i socket si trovano con due referenze. Questo fa si che quando il
-padre chiude \var{sock\_fd} esso resta con una referenza da parte del figlio,
-e sarà definitivamente chiuso solo quando quest'ultimo, dopo aver completato
-le sue operazioni, chiamerà (\texttt{\small 44}) la funzione \func{close}.
-
-In realtà per il figlio non sarebbe necessaria nessuna chiamata a
-\func{close}, in quanto con la \func{exit} finale (\texttt{\small 45}) tutti i
-file descriptor, quindi anche quelli associati ai socket, vengono
-automaticamente chiusi. Tuttavia si è preferito effettuare esplicitamente le
-chiusure per avere una maggiore chiarezza del codice, e per evitare eventuali
-errori, prevenendo ad esempio un uso involontario del \textit{listening
- descriptor}.
-
-Si noti invece come sia essenziale che il padre chiuda ogni volta il socket
-connesso dopo la \func{fork}; se così non fosse nessuno di questi socket
-sarebbe effettivamente chiuso dato che alla chiusura da parte del figlio
-resterebbe ancora un riferimento nel padre. Si avrebbero così due effetti: il
-padre potrebbe esaurire i descrittori disponibili (che sono un numero limitato
-per ogni processo) e soprattutto nessuna delle connessioni con i client
-verrebbe chiusa.
-
-Come per ogni server iterativo il lavoro di risposta viene eseguito
-interamente dal processo figlio. Questo si incarica (\texttt{\small 33}) di
-chiamare \func{time} per leggere il tempo corrente, e di stamparlo
-(\texttt{\small 34}) sulla stringa contenuta in \var{buffer} con l'uso di
-\func{snprintf} e \func{ctime}. Poi la stringa viene scritta (\texttt{\small
- 35--38}) sul socket, controllando che non ci siano errori. Anche in questo
-caso si è evitato il ricorso a \func{FullWrite} in quanto la stringa è
-estremamente breve e verrà senz'altro scritta in un singolo segmento.
-
-Inoltre nel caso sia stato abilitato il \textit{logging} delle connessioni, si
-provvede anche (\texttt{\small 39--42}) a stampare sullo standard output
-l'indirizzo e la porta da cui il client ha effettuato la connessione, usando
-i valori contenuti nelle strutture restituite da \func{accept}, eseguendo le
-opportune conversioni con \func{inet\_ntop} e \func{atohs}.
-
-Ancora una volta l'esempio è estremamente semplificato, si noti come di nuovo
-non si sia gestita né la terminazione del processo né il suo uso come demone,
-che tra l'altro sarebbe stato incompatibile con l'uso della opzione di logging
-che stampa gli indirizzi delle connessioni sullo standard output. Un altro
-aspetto tralasciato è la gestione della terminazione dei processi figli,
-torneremo su questo più avanti quando tratteremo alcuni esempi di server più
-complessi.
-
-
-
-\section{Un esempio più completo: il servizio \textit{echo}}
-\label{sec:TCP_echo_application}
-
-L'esempio precedente, basato sul servizio \textit{daytime}, è un esempio molto
-elementare, in cui il flusso dei dati va solo nella direzione dal server al
-client. In questa sezione esamineremo un esempio di applicazione client/server
-un po' più complessa, che usi i socket TCP per una comunicazione in entrambe
-le direzioni.
-
-Ci limiteremo a fornire una implementazione elementare, che usi solo le
-funzioni di base viste finora, ma prenderemo in esame, oltre al comportamento
-in condizioni normali, anche tutti i possibili scenari particolari (errori,
-sconnessione della rete, crash del client o del server durante la connessione)
-che possono avere luogo durante l'impiego di un'applicazione di rete, partendo
-da una versione primitiva che dovrà essere rimaneggiata di volta in volta per
-poter tenere conto di tutte le evenienze che si possono manifestare nella vita
-reale di un'applicazione di rete, fino ad arrivare ad un'implementazione
-completa.
-
-
-\subsection{Il servizio \textit{echo}}
-\label{sec:TCP_echo}
-
-
-Nella ricerca di un servizio che potesse fare da esempio per una comunicazione
-bidirezionale, si è deciso, seguendo la scelta di Stevens in \cite{UNP1}, di
-usare il servizio \textit{echo}, che si limita a restituire in uscita quanto
-immesso in ingresso. Infatti, nonostante la sua estrema semplicità, questo
-servizio costituisce il prototipo ideale per una generica applicazione di rete
-in cui un server risponde alle richieste di un client. Nel caso di una
-applicazione più complessa quello che si potrà avere in più è una elaborazione
-dell'input del client, che in molti casi viene interpretato come un comando,
-da parte di un server che risponde fornendo altri dati in uscita.
-
-Il servizio \textit{echo} è uno dei servizi standard solitamente provvisti
-direttamente dal superserver \cmd{inetd}, ed è definito
-dall'\href{http://www.ietf.org/rfc/rfc0862.txt}{RFC~862}. Come dice il nome il
-servizio deve riscrivere indietro sul socket i dati che gli vengono inviati in
-ingresso. L'RFC descrive le specifiche del servizio sia per TCP che UDP, e per
-il primo stabilisce che una volta stabilita la connessione ogni dato in
-ingresso deve essere rimandato in uscita fintanto che il chiamante non ha
-chiude la connessione. Al servizio è assegnata la porta riservata 7.
-
-Nel nostro caso l'esempio sarà costituito da un client che legge una linea di
-caratteri dallo standard input e la scrive sul server. A sua volta il server
-leggerà la linea dalla connessione e la riscriverà immutata all'indietro. Sarà
-compito del client leggere la risposta del server e stamparla sullo standard
-output.
-
-
-\subsection{Il client: prima versione}
-\label{sec:TCP_echo_client}
-
-Il codice della prima versione del client per il servizio \textit{echo},
-disponibile nel file \file{TCP\_echo\_first.c}, è riportato in
-\figref{fig:TCP_echo_client_1}. Esso ricalca la struttura del precedente
-client per il servizio \textit{daytime} (vedi
-\secref{sec:TCP_daytime_client}), e la prima parte (\texttt{\small 10--27}) è
-sostanzialmente identica, a parte l'uso di una porta diversa.
-
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15.6 cm}
- \includecodesample{listati/TCP_echo_first.c}
- \end{minipage}
- \normalsize
- \caption{Codice della prima versione del client \textit{echo}.}
- \label{fig:TCP_echo_client_1}
-\end{figure}
-
-Al solito si è tralasciata la sezione relativa alla gestione delle opzioni a
-riga di comando. Una volta dichiarate le variabili, si prosegue
-(\texttt{\small 10--13}) con della creazione del socket con l'usuale controllo
-degli errori, alla preparazione (\texttt{\small 14--17}) della struttura
-dell'indirizzo, che stavolta usa la porta 7 riservata al servizio
-\textit{echo}, infine si converte (\texttt{\small 18--22}) l'indirizzo
-specificato a riga di comando. A questo punto (\texttt{\small 23--27}) si può
-eseguire la connessione al server secondo la stessa modalità usata in
-\secref{sec:TCP_daytime_client}.
-
-Completata la connessione, per gestire il funzionamento del protocollo si usa
-la funzione \code{ClientEcho}, il cui codice si è riportato a parte in
-\figref{fig:TCP_client_echo_sub}. Questa si preoccupa di gestire tutta la
-comunicazione, leggendo una riga alla volta dallo standard input \file{stdin},
-scrivendola sul socket e ristampando su \file{stdout} quanto ricevuto in
-risposta dal server. Al ritorno dalla funzione (\texttt{\small 30--31}) anche
-il programma termina.
-
-La funzione \code{ClientEcho} utilizza due buffer (\texttt{\small 3}) per
-gestire i dati inviati e letti sul socket. La comunicazione viene gestita
-all'interno di un ciclo (\texttt{\small 5--10}), i dati da inviare sulla
-connessione vengono presi dallo \file{stdin} usando la funzione \func{fgets},
-che legge una linea di testo (terminata da un \texttt{CR} e fino al massimo di
-\const{MAXLINE} caratteri) e la salva sul buffer di invio.
-
-Si usa poi (\texttt{\small 6}) la funzione \func{FullWrite}, vista in
-\secref{sec:sock_io_behav}, per scrivere i dati sul socket, gestendo
-automaticamente l'invio multiplo qualora una singola \func{write} non sia
-sufficiente. I dati vengono riletti indietro (\texttt{\small 7}) con una
-\func{read}\footnote{si è fatta l'assunzione implicita che i dati siano
- contenuti tutti in un solo segmento, così che la chiamata a \texttt{read} li
- restituisca sempre tutti; avendo scelto una dimensione ridotta per il buffer
- questo sarà sempre vero, vedremo più avanti come superare il problema di
- rileggere indietro tutti e soli i dati disponibili, senza bloccarsi.} sul
-buffer di ricezione e viene inserita (\texttt{\small 8}) la terminazione della
-stringa e per poter usare (\texttt{\small 9}) la funzione \func{fputs} per
-scriverli su \file{stdout}.
-
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15.6cm}
- \includecodesample{listati/ClientEcho.c}
- \end{minipage}
- \normalsize
- \caption{Codice della prima versione della funzione \texttt{ClientEcho} per
- la gestione del servizio \textit{echo}.}
- \label{fig:TCP_client_echo_sub}
-\end{figure}
-
-Quando si concluderà l'invio di dati mandando un end-of-file sullo standard
-input si avrà il ritorno di \func{fgets} con un puntatore nullo (si riveda
-quanto spiegato in \secref{sec:file_line_io}) e la conseguente uscita dal
-ciclo; al che la subroutine ritorna ed il nostro programma client termina.
-
-Si può effettuare una verifica del funzionamento del client abilitando il
-servizio \textit{echo} nella configurazione di \cmd{initd} sulla propria
-macchina ed usandolo direttamente verso di esso in locale, vedremo in
-dettaglio più avanti (in \secref{sec:TCP_echo_startup}) il funzionamento del
-programma, usato però con la nostra versione del server \textit{echo}, che
-illustriamo immediatamente.
-
-
-\subsection{Il server: prima versione}
-\label{sec:TCPsimp_server_main}
-
-La prima versione del server, contenuta nel file \file{TCP\_echod\_first.c}, è
-riportata in \figref{fig:TCP_echo_server_first_code}. Come abbiamo fatto per
-il client anche il server è stato diviso in un corpo principale, costituito
-dalla funzione \code{main}, che è molto simile a quello visto nel precedente
-esempio per il server del servizio \textit{daytime} di
-\secref{sec:TCP_daytime_cunc_server}, e da una funzione ausiliaria
-\code{ServEcho} che si cura della gestione del servizio.
-
-\begin{figure}[!htbp]
- \footnotesize \centering
- \begin{minipage}[c]{15.6cm}
- \includecodesample{listati/TCP_echod_first.c}
- \end{minipage}
- \normalsize
- \caption{Codice del corpo principale della prima versione del server
- per il servizio \textit{echo}.}
- \label{fig:TCP_echo_server_first_code}
-\end{figure}
-
-In questo caso però, rispetto a quanto visto nell'esempio di
-\figref{fig:TCP_daytime_cunc_server_code} si è preferito scrivere il server
-curando maggiormente alcuni dettagli, per tenere conto anche di alcune
-esigenze generali (che non riguardano direttamente la rete), come la
-possibilità di lanciare il server anche in modalità interattiva e la cessione
-dei privilegi di amministratore non appena questi non sono più necessari.
-
-La sezione iniziale del programma (\texttt{\small 8--21}) è la stessa del
-server di \secref{sec:TCP_daytime_cunc_server}, ed ivi descritta in dettaglio:
-crea il socket, inizializza l'indirizzo e esegue \func{bind}; dato che
-quest'ultima funzione viene usata su una porta riservata, il server dovrà
-essere eseguito da un processo con i privilegi di amministratore, pena il
-fallimento della chiamata.
-
-Una volta eseguita la funzione \func{bind} però i privilegi di amministratore
-non sono più necessari, per questo è sempre opportuno rilasciarli, in modo da
-evitare problemi in caso di eventuali vulnerabilità del server. Per questo
-prima (\texttt{\small 22--26}) si esegue \func{setgid} per assegnare il
-processo ad un gruppo senza privilegi,\footnote{si è usato il valore 65534,
- ovvero -1 per il formato \ctyp{short}, che di norma in tutte le
- distribuzioni viene usato per identificare il gruppo \texttt{nogroup} e
- l'utente \texttt{nobody}, usati appunto per eseguire programmi che non
- richiedono nessun privilegio particolare.} e poi si ripete (\texttt{\small
- 27--30}) l'operazione usando \func{setuid} per cambiare anche
-l'utente.\footnote{si tenga presente che l'ordine in cui si eseguono queste
- due operazioni è importante, infatti solo avendo i privilegi di
- amministratore si può cambiare il gruppo di un processo ad un'altro di cui
- non si fa parte, per cui chiamare prima \func{setuid} farebbe fallire una
- successiva chiamata a \func{setgid}. Inoltre si ricordi (si riveda quanto
- esposto in \secref{sec:proc_perms}) che usando queste due funzioni il
- rilascio dei privilegi è irreversibile.} Infine (\texttt{\small 30--36}),
-qualora sia impostata la variabile \var{demonize}, prima (\texttt{\small 31})
-si apre il sistema di logging per la stampa degli errori, e poi
-(\texttt{\small 32--35}) si invoca \func{daemon} per eseguire in background il
-processo come demone.
-
-A questo punto il programma riprende di nuovo lo schema già visto usato dal
-server per il servizio \textit{daytime}, con l'unica differenza della chiamata
-alla funzione \code{PrintErr}, riportata in \figref{fig:TCP_PrintErr}, al
-posto di \func{perror} per la stampa degli errori.
-
-Si inizia con il porre (\texttt{\small 37--41}) in ascolto il socket, e poi si
-esegue indefinitamente il ciclo principale (\texttt{\small 42--58}).
-All'interno di questo si ricevono (\texttt{\small 43--46}) le connessioni,
-creando (\texttt{\small 47--50}) un processo figlio per ciascuna di esse.
-Quest'ultimo (\texttt{\small 51--55}), chiuso (\texttt{\small 52}) il
-\textit{listening socket}, esegue (\texttt{\small 53}) la funzione di gestione
-del servizio \code{ServEcho}, ed al ritorno di questa (\texttt{\small 54})
-esce.
-
-Il padre invece si limita (\texttt{\small 56}) a chiudere il \textit{connected
- socket} per ricominciare da capo il ciclo in attesa di nuove connessioni. In
-questo modo si ha un server concorrente. La terminazione del padre non è
-gestita esplicitamente, e deve essere effettuata inviando un segnale al
-processo.
-
-Avendo trattato direttamente la gestione del programma come demone, si è
-dovuto anche provvedere alla necessità di poter stampare eventuali messaggi di
-errore attraverso il sistema del \textit{syslog} trattato in
-\secref{sec:sess_daemon}. Come accennato questo è stato fatto utilizzando come
-\textit{wrapper} la funzione \code{PrintErr}, il cui codice è riportato in
-\figref{fig:TCP_PrintErr}.
-
-In essa ci si limita a controllare (\texttt{\small 2}) se è stato impostato
-(valore attivo per default) l'uso come demone, nel qual caso (\texttt{\small
- 3}) si usa \func{syslog} (vedi \secref{sec:sess_daemon}) per stampare il
-messaggio di errore fornito come argomento sui log di sistema. Se invece si è
-in modalità interattiva (attivabile con l'opzione \texttt{-i}) si usa
-(\texttt{\small 5}) semplicemente la funzione \func{perror} per stampare sullo
-standard error.
-
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15.6cm}
- \includecodesample{listati/PrintErr.c}
- \end{minipage}
- \normalsize
- \caption{Codice della funzione \code{PrintErr} per la
- generalizzazione della stampa degli errori sullo standard input o
- attraverso il \texttt{syslog}.}
- \label{fig:TCP_PrintErr}
-\end{figure}
-
-La gestione del servizio \textit{echo} viene effettuata interamente nella
-funzione \code{ServEcho}, il cui codice è mostrato in
-\figref{fig:TCP_ServEcho_first}, e la comunicazione viene gestita all'interno
-di un ciclo (\texttt{\small 6--13}). I dati inviati dal client vengono letti
-(\texttt{\small 6}) dal socket con una semplice \func{read}, di cui non si
-controlla lo stato di uscita, assumendo che ritorni solo in presenza di dati
-in arrivo. La riscrittura (\texttt{\small 7}) viene invece gestita dalla
-funzione \func{FullWrite} (descritta in \figref{fig:sock_FullWrite_code}) che
-si incarica di tenere conto automaticamente della possibilità che non tutti i
-dati di cui è richiesta la scrittura vengano trasmessi con una singola
-\func{write}.
-
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15.6cm}
- \includecodesample{listati/ServEcho_first.c}
- \end{minipage}
- \normalsize
- \caption{Codice della prima versione della funzione \code{ServEcho} per la
- gestione del servizio \textit{echo}.}
- \label{fig:TCP_ServEcho_first}
-\end{figure}
-
-In caso di errore di scrittura (si ricordi che \func{FullWrite} restituisce un
-valore nullo in caso di successo) si provvede (\texttt{\small 8--10}) a
-stampare il relativo messaggio con \func{PrintErr}. Quando il client chiude
-la connessione il ricevimento del FIN fa ritornare la \func{read} con un
-numero di byte letti pari a zero, il che causa l'uscita dal ciclo e il ritorno
-(\texttt{\small 12}) della funzione, che a sua volta causa la terminazione del
-processo figlio.
-
-
-\subsection{L'avvio e il funzionamento normale}
-\label{sec:TCP_echo_startup}
-
-Benché il codice dell'esempio precedente sia molto ridotto, esso ci permetterà
-di considerare in dettaglio le varie problematiche che si possono incontrare
-nello scrivere un'applicazione di rete. Infatti attraverso l'esame delle sue
-modalità di funzionamento normali, all'avvio e alla terminazione, e di quello
-che avviene nelle varie situazioni limite, da una parte potremo approfondire
-la comprensione del protocollo TCP/IP e dall'altra ricavare le indicazioni
-necessarie per essere in grado di scrivere applicazioni robuste, in grado di
-gestire anche i casi limite.
-
-Il primo passo è compilare e lanciare il server (da root, per poter usare la
-porta 7 che è riservata), alla partenza esso eseguirà l'apertura passiva con
-la sequenza delle chiamate a \func{socket}, \func{bind}, \func{listen} e poi
-si bloccherà nella \func{accept}. A questo punto si potrà controllarne lo
-stato con \cmd{netstat}:
-\begin{verbatim}
-[piccardi@roke piccardi]$ netstat -at
-Active Internet connections (servers and established)
-Proto Recv-Q Send-Q Local Address Foreign Address State
-...
-tcp 0 0 *:echo *:* LISTEN
-...
-\end{verbatim} %$
-che ci mostra come il socket sia in ascolto sulla porta richiesta, accettando
-connessioni da qualunque indirizzo e da qualunque porta e su qualunque
-interfaccia locale.
-
-A questo punto si può lanciare il client, esso chiamerà \func{socket} e
-\func{connect}; una volta completato il three way handshake la connessione è
-stabilita; la \func{connect} ritornerà nel client\footnote{si noti che è
- sempre la \func{connect} del client a ritornare per prima, in quanto
- questo avviene alla ricezione del secondo segmento (l'ACK del server) del
- three way handshake, la \func{accept} del server ritorna solo dopo
- un altro mezzo RTT quando il terzo segmento (l'ACK del client) viene
- ricevuto.} e la \func{accept} nel server, ed usando di nuovo
-\cmd{netstat} otterremmo che:
-\begin{verbatim}
-Active Internet connections (servers and established)
-Proto Recv-Q Send-Q Local Address Foreign Address State
-tcp 0 0 *:echo *:* LISTEN
-tcp 0 0 roke:echo gont:32981 ESTABLISHED
-\end{verbatim}
-mentre per quanto riguarda l'esecuzione dei programmi avremo che:
-\begin{itemize}
-\item il client chiama la funzione \code{ClientEcho} che si blocca sulla
- \func{fgets} dato che non si è ancora scritto nulla sul terminale.
-\item il server eseguirà una \func{fork} facendo chiamare al processo figlio
- la funzione \code{ServEcho}, quest'ultima si bloccherà sulla \func{read}
- dal socket sul quale ancora non sono presenti dati.
-\item il processo padre del server chiamerà di nuovo \func{accept}
- bloccandosi fino all'arrivo di un'altra connessione.
-\end{itemize}
-e se usiamo il comando \cmd{ps} per esaminare lo stato dei processi otterremo
-un risultato del tipo:
-\begin{verbatim}
-[piccardi@roke piccardi]$ ps ax
- PID TTY STAT TIME COMMAND
- ... ... ... ... ...
- 2356 pts/0 S 0:00 ./echod
- 2358 pts/1 S 0:00 ./echo 127.0.0.1
- 2359 pts/0 S 0:00 ./echod
-\end{verbatim} %$
-(dove si sono cancellate le righe inutili) da cui si evidenzia la presenza di
-tre processi, tutti in stato di \textit{sleep} (vedi
-\tabref{tab:proc_proc_states}).
-
-Se a questo punto si inizia a scrivere qualcosa sul client non sarà trasmesso
-niente fin tanto che non si prema il tasto di a capo (si ricordi quanto detto
-in \secref{sec:file_line_io} a proposito dell'I/O su terminale), solo allora
-\func{fgets} ritornerà ed il client scriverà quanto immesso sul socket, per
-poi passare a rileggere quanto gli viene inviato all'indietro dal server, che
-a sua volta sarà inviato sullo standard output, che nel caso ne provoca
-l'immediatamente stampa a video.
-
-
-\subsection{La conclusione normale}
-\label{sec:TCP_echo_conclusion}
-
-Tutto quello che scriveremo sul client sarà rimandato indietro dal server e
-ristampato a video fintanto che non concluderemo l'immissione dei dati; una
-sessione tipica sarà allora del tipo:
-\begin{verbatim}
-[piccardi@roke sources]$ ./echo 127.0.0.1
-Questa e` una prova
-Questa e` una prova
-Ho finito
-Ho finito
-\end{verbatim} %$
-che termineremo inviando un EOF dal terminale (usando la combinazione di tasti
-ctrl-D, che non compare a schermo); se eseguiamo un \cmd{netstat} a questo
-punto avremo:
-\begin{verbatim}
-[piccardi@roke piccardi]$ netstat -at
-tcp 0 0 *:echo *:* LISTEN
-tcp 0 0 localhost:33032 localhost:echo TIME_WAIT
-\end{verbatim} %$
-con il client che entra in \texttt{TIME\_WAIT}.
-
-Esaminiamo allora in dettaglio la sequenza di eventi che porta alla
-terminazione normale della connessione, che ci servirà poi da riferimento
-quando affronteremo il comportamento in caso di conclusioni anomale:
-
-\begin{enumerate}
-\item inviando un carattere di EOF da terminale la \func{fgets} ritorna
- restituendo un puntatore nullo che causa l'uscita dal ciclo di \code{while},
- così la funzione \code{ClientEcho} ritorna.
-\item al ritorno di \code{ClientEcho} ritorna anche la funzione \code{main}, e
- come parte del processo terminazione tutti i file descriptor vengono chiusi
- (si ricordi quanto detto in \secref{sec:proc_term_conclusion}); questo causa
- la chiusura del socket di comunicazione; il client allora invierà un FIN al
- server a cui questo risponderà con un ACK. A questo punto il client verrà a
- trovarsi nello stato \texttt{FIN\_WAIT\_2} ed il server nello stato
- \texttt{CLOSE\_WAIT} (si riveda quanto spiegato in
- \secref{sec:TCP_conn_term}).
-\item quando il server riceve il FIN la \func{read} del processo figlio che
- gestisce la connessione ritorna restituendo 0 causando così l'uscita dal
- ciclo e il ritorno di \code{ServEcho}, a questo punto il processo figlio
- termina chiamando \func{exit}.
-\item all'uscita del figlio tutti i file descriptor vengono chiusi, la
- chiusura del socket connesso fa sì che venga effettuata la sequenza finale
- di chiusura della connessione, viene emesso un FIN dal server che riceverà
- un ACK dal client, a questo punto la connessione è conclusa e il client
- resta nello stato \texttt{TIME\_WAIT}.
-\end{enumerate}
-
-
-\subsection{La gestione dei processi figli}
-\label{sec:TCP_child_hand}
-
-Tutto questo riguarda la connessione, c'è però da tenere conto dell'effetto
-del procedimento di chiusura del processo figlio nel server (si veda quanto
-esaminato in \secref{sec:proc_termination}). In questo caso avremo l'invio del
-segnale \const{SIGCHLD} al padre, ma dato che non si è installato un
-gestore e che l'azione predefinita per questo segnale è quella di essere
-ignorato, non avendo predisposto la ricezione dello stato di terminazione,
-otterremo che il processo figlio entrerà nello stato di zombie\index{zombie}
-(si riveda quanto illustrato in \secref{sec:sig_sigchld}), come risulterà
-ripetendo il comando \cmd{ps}:
-\begin{verbatim}
- 2356 pts/0 S 0:00 ./echod
- 2359 pts/0 Z 0:00 [echod <defunct>]
-\end{verbatim}
-
-Dato che non è il caso di lasciare processi zombie\index{zombie}, occorrerà
-ricevere opportunamente lo stato di terminazione del processo (si veda
-\secref{sec:proc_wait}), cosa che faremo utilizzando \const{SIGCHLD} secondo
-quanto illustrato in \secref{sec:sig_sigchld}. Una prima modifica al nostro
-server è pertanto quella di inserire la gestione della terminazione dei
-processi figli attraverso l'uso di un gestore. Per questo useremo la funzione
-\code{Signal} (che abbiamo illustrato in \figref{fig:sig_Signal_code}), per
-installare il gestore che riceve i segnali dei processi figli terminati già
-visto in \figref{fig:sig_sigchld_handl}. Basterà allora aggiungere il
-seguente codice: \includecodesnip{listati/sigchildhand.c}
-\noindent
-all'esempio illustrato in \figref{fig:TCP_echo_server_first_code}.
-
-In questo modo però si introduce un altro problema. Si ricordi infatti che,
-come spiegato in \secref{sec:sig_gen_beha}, quando un programma si trova in
-stato di \texttt{sleep} durante l'esecuzione di una system call, questa viene
-interrotta alla ricezione di un segnale. Per questo motivo, alla fine
-dell'esecuzione del gestore del segnale, se questo ritorna, il programma
-riprenderà l'esecuzione ritornando dalla system call interrotta con un errore
-di \errcode{EINTR}.
-
-Vediamo allora cosa comporta tutto questo nel nostro caso: quando si chiude il
-client, il processo figlio che gestisce la connessione terminerà, ed il padre,
-per evitare la creazione di zombie, riceverà il segnale \const{SIGCHLD}
-eseguendo il relativo gestore. Al ritorno del gestore però l'esecuzione nel
-padre ripartirà subito con il ritorno della funzione \func{accept} (a meno di
-un caso fortuito in cui il segnale arriva durante l'esecuzione del programma
-in risposta ad una connessione) con un errore di \errcode{EINTR}. Non avendo
-previsto questa eventualità il programma considera questo un errore fatale
-terminando a sua volta con un messaggio del tipo:
-\begin{verbatim}
-[root@gont sources]# ./echod -i
-accept error: Interrupted system call
-\end{verbatim}%#
-
-Come accennato in \secref{sec:sig_gen_beha} le conseguenze di questo
-comportamento delle system call possono essere superate in due modi diversi,
-il più semplice è quello di modificare il codice di \func{Signal} per
-richiedere il riavvio automatico delle system call interrotte secondo la
-semantica di BSD, usando l'opzione \const{SA\_RESTART} di \func{sigaction};
-rispetto a quanto visto in \figref{fig:sig_Signal_code}. Definiremo allora la
-nuova funzione \func{SignalRestart}\footnote{anche questa è definita, insieme
- alle altre funzioni riguardanti la gestione dei segnali, nel file
- \file{SigHand.c}, il cui contento completo può essere trovato negli esempi
- allegati.} come mostrato in \figref{fig:sig_SignalRestart_code}, ed
-installeremo il gestore usando quest'ultima.
-
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15.6cm}
- \includecodesample{listati/SignalRestart.c}
- \end{minipage}
- \normalsize
- \caption{La funzione \funcd{SignalRestart}, che installa un gestore di
- segnali in semantica BSD per il riavvio automatico delle system call
- interrotte.}
- \label{fig:sig_SignalRestart_code}
-\end{figure}
-
-Come si può notare questa funzione è identica alla precedente \func{Signal},
-illustrata in \figref{fig:sig_Signal_code}, solo che in questo caso invece di
-inizializzare a zero il campo \var{sa\_flags} di \struct{sigaction}, lo si
-inizializza (\texttt{\small 5}) al valore \const{SA\_RESTART}. Usando questa
-funzione al posto di \func{Signal} nel server non è necessaria nessuna altra
-modifica: le system call interrotte saranno automaticamente riavviate, e
-l'errore \errcode{EINTR} non si manifesterà più.
-
-La seconda soluzione è più invasiva e richiede di controllare tutte le volte
-l'errore restituito dalle varie system call, ripetendo la chiamata qualora
-questo corrisponda ad \errcode{EINTR}. Questa soluzione ha però il pregio
-della portabilità, infatti lo standard POSIX dice che la funzionalità di
-riavvio automatico delle system call, fornita da \const{SA\_RESTART}, è
-opzionale, per cui non è detto che essa sia disponibile su qualunque sistema.
-Inoltre in certi casi,\footnote{Stevens in \cite{UNP1} accenna che la maggior
- parte degli Unix derivati da BSD non fanno ripartire \func{select}; altri
- non riavviano neanche \func{accept} e \func{recvfrom}, cosa che invece nel
- caso di Linux viene sempre fatta.} anche quando questa è presente, non è
-detto possa essere usata con \func{accept}.
-
-
-La portabilità nella gestione dei segnali però viene al costo di una
-riscrittura parziale del server, la nuova versione di questo, in cui si sono
-introdotte una serie di nuove opzioni che ci saranno utili per il debug, è
-mostrata in \figref{fig:TCP_echo_server_code_second}, dove si sono riportate
-la sezioni di codice modificate nella seconda versione del programma, il
-sorgente completo di quest'ultimo si trova nel file
-\file{TCP\_echod\_second.c} dei sorgenti allegati alla guida.
-
-La prima modifica effettuata è stata quella di introdurre una nuova opzione a
-riga di comando, \texttt{-c}, che permette di richiedere il comportamento
-compatibile nella gestione di \const{SIGCHLD} al posto della semantica BSD
-impostando la variabile \var{compat} ad un valore non nullo. Questa è
-preimpostata al valore nullo, cosicché se non si usa questa opzione il
-comportamento di default del server è di usare la semantica BSD.
-
-Una seconda opzione aggiunta è quella di inserire un tempo di attesa fisso
-specificato in secondi fra il ritorno della funzione \func{listen} e la
-chiamata di \func{accept}, specificabile con l'opzione \texttt{-w}, che
-permette di impostare la variabile \var{waiting}. Infine si è introdotta una
-opzione \texttt{-d} per abilitare il debugging che imposta ad un valore non
-nullo la variabile \var{debugging}. Al solito si è omessa da
-\figref{fig:TCP_echo_server_code_second} la sezione di codice relativa alla
-gestione di tutte queste opzioni, che può essere trovata nel sorgente del
-programma.
-
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15.6cm}
- \includecodesample{listati/TCP_echod_second.c}
- \end{minipage}
- \normalsize
- \caption{La sezione nel codice della seconda versione del server
- per il servizio \textit{echo} modificata per tener conto dell'interruzione
- delle system call.}
- \label{fig:TCP_echo_server_code_second}
-\end{figure}
-
-Vediamo allora come è cambiato il nostro server; una volta definite le
-variabili e trattate le opzioni il primo passo (\texttt{\small 9--13}) è
-verificare la semantica scelta per la gestione di \const{SIGCHLD}, a seconda
-del valore di \var{compat} (\texttt{\small 9}) si installa il gestore con la
-funzione \func{Signal} (\texttt{\small 10}) o con \texttt{SignalRestart}
-(\texttt{\small 12}), essendo quest'ultimo il valore di default.
-
-Tutta la sezione seguente, che crea il socket, cede i privilegi di
-amministratore ed eventualmente lancia il programma come demone, è rimasta
-invariata e pertanto è stata omessa in
-\figref{fig:TCP_echo_server_code_second}; l'unica modifica effettuata prima
-dell'entrata nel ciclo principale è stata quella di aver introdotto, subito
-dopo la chiamata (\texttt{\small 17--20}) alla funzione \func{listen}, una
-eventuale pausa con una condizione (\texttt{\small 21}) sulla variabile
-\var{waiting}, che viene inizializzata, con l'opzione \code{-w Nsec}, al
-numero di secondi da aspettare (il valore preimpostato è nullo).
-
-Si è potuto lasciare inalterata tutta la sezione di creazione del socket
-perché nel server l'unica chiamata ad una system call critica, che può essere
-interrotta dall'arrivo di \const{SIGCHLD}, è quella ad \func{accept}, che è
-l'unica funzione che può mettere il processo padre in stato di sleep nel
-periodo in cui un figlio può terminare; si noti infatti come le altre
-\textit{slow system call}\footnote{si ricordi la distinzione fatta in
- \secref{sec:sig_gen_beha}.} o sono chiamate prima di entrare nel ciclo
-principale, quando ancora non esistono processi figli, o sono chiamate dai
-figli stessi e non risentono di \const{SIGCHLD}.
-
-Per questo l'unica modifica sostanziale nel ciclo principale (\texttt{\small
- 23--42}), rispetto precedente versione di \figref{fig:TCP_ServEcho_first}, è
-nella sezione (\texttt{\small 26--30}) in cui si effettua la chiamata di
-\func{accept}. Quest'ultima viene effettuata (\texttt{\small 26--27})
-all'interno di un ciclo di \code{while}\footnote{la sintassi del C relativa a
- questo ciclo può non essere del tutto chiara. In questo caso infatti si è
- usato un ciclo vuoto che non esegue nessuna istruzione, in questo modo
- quello che viene ripetuto con il ciclo è soltanto il codice che esprime la
- condizione all'interno del \code{while}.} che la ripete indefinitamente
-qualora in caso di errore il valore di \var{errno} sia \errcode{EINTR}. Negli
-altri casi si esce in caso di errore effettivo (\texttt{\small 27--29}),
-altrimenti il programma prosegue.
-
-Si noti che in questa nuova versione si è aggiunta una ulteriore sezione
-(\texttt{\small 31--39}) di aiuto per il debug del programma, che eseguita con
-un controllo (\texttt{\small 31}) sul valore della variabile \var{debugging}
-impostato dall'opzione \texttt{-d}. Qualora questo sia nullo, come
-preimpostato, non accade nulla. altrimenti (\texttt{\small 32}) l'indirizzo
-ricevuto da \var{accept} viene convertito in una stringa che poi
-(\texttt{\small 33--38}) viene opportunamente stampata o sullo schermo o nei
-log.
-
-
-
-
-\section{I vari scenari critici}
-\label{sec:TCP_echo_critical}
-
-Con le modifiche viste in \secref{sec:TCP_child_hand} il nostro esempio
-diventa in grado di affrontare la gestione ordinaria delle connessioni, ma un
-server di rete deve tenere conto che, al contrario di quanto avviene per i
-server che operano nei confronti di processi presenti sulla stessa macchina,
-la rete è di sua natura inaffidabile, per cui è necessario essere in grado di
-gestire tutta una serie di situazioni critiche che non esistono per i processi
-locali.
-
-
-\subsection{La terminazione precoce della connessione}
-\label{sec:TCP_conn_early_abort}
-
-La prima situazione critica è quella della terminazione precoce, causata da un
-qualche errore sulla rete, della connessione effettuata da un client. Come
-accennato in \secref{sec:TCP_func_accept} la funzione \func{accept} riporta
-tutti gli eventuali errori di rete pendenti su una connessione sul
-\textit{connected socket}. Di norma questo non è un problema, in quanto non
-appena completata la connessione, \func{accept} ritorna e l'errore sarà
-rilevato in seguito, dal processo che gestisce la connessione, alla prima
-chiamata di una funzione che opera sul socket.
-
-È però possibile, dal punto di vista teorico, incorrere anche in uno scenario
-del tipo di quello mostrato in \figref{fig:TCP_early_abort}, in cui la
-connessione viene abortita sul lato client per un qualche errore di rete con
-l'invio di un segmento RST, prima che nel server sia stata chiamata la
-funzione \func{accept}.
-
-\begin{figure}[htb]
- \centering
- \includegraphics[width=10cm]{img/tcp_client_early_abort}
- \caption{Un possibile caso di terminazione precoce della connessione.}
- \label{fig:TCP_early_abort}
-\end{figure}
-
-Benché questo non sia un fatto comune, un evento simile può essere osservato
-con dei server molto occupati. In tal caso, con una struttura del server
-simile a quella del nostro esempio, in cui la gestione delle singole
-connessioni è demandata a processi figli, può accadere che il three way
-handshake venga completato e la relativa connessione abortita subito dopo,
-prima che il padre, per via del carico della macchina, abbia fatto in tempo ad
-eseguire la chiamata ad \func{accept}. Di nuovo si ha una situazione analoga
-a quella illustrata in \figref{fig:TCP_early_abort}, in cui la connessione
-viene stabilita, ma subito dopo si ha una condizione di errore che la chiude
-prima che essa sia stata accettata dal programma.
-
-Questo significa che, oltre alla interruzione da parte di un segnale, che
-abbiamo trattato in \secref{sec:TCP_child_hand} nel caso particolare di
-\const{SIGCHLD}, si possono ricevere altri errori non fatali all'uscita di
-\func{accept}, che come nel caso precedente, necessitano semplicemente la
-ripetizione della chiamata senza che si debba uscire dal programma. In questo
-caso anche la versione modificata del nostro server non sarebbe adatta, in
-quanto uno di questi errori causerebbe la terminazione dello stesso. In Linux
-i possibili errori di rete non fatali, riportati sul socket connesso al
-ritorno di \func{accept}, sono \errcode{ENETDOWN}, \errcode{EPROTO},
-\errcode{ENOPROTOOPT}, \errcode{EHOSTDOWN}, \errcode{ENONET},
-\errcode{EHOSTUNREACH}, \errcode{EOPNOTSUPP} e \errcode{ENETUNREACH}.
-
-Si tenga presente che questo tipo di terminazione non è riproducibile
-terminando il client prima della chiamata ad \func{accept}, come si potrebbe
-fare usando l'opzione \texttt{-w} per introdurre una pausa dopo il lancio del
-demone, in modo da poter avere il tempo per lanciare e terminare una
-connessione usando il programma client. In tal caso infatti, alla terminazione
-del client, il socket associato alla connessione viene semplicemente chiuso,
-attraverso la sequenza vista in \secref{sec:TCP_conn_term}, per cui la
-\func{accept} ritornerà senza errori, e si avrà semplicemente un end-of-file
-al primo accesso al socket. Nel caso di Linux inoltre, anche qualora si
-modifichi il client per fargli gestire l'invio di un segmento di RST alla
-chiusura dal socket (come suggerito da Stevens in \cite{UNP1}), non si ha
-nessun errore al ritorno di \funcd{accept} quanto un errore di
-\errcode{ECONNRESET} al primo tentativo di accesso al socket.
-
-
-
-\subsection{Il crollo del server}
-\label{sec:TCP_server_crash}
-
-Un secondo caso critico è quello in cui si ha il crollo del server. In tal
-caso si suppone che il processo del server termini per un errore fatale, cosa
-che potremo simulare inviandogli un segnale di terminazione. La conclusione
-del processo comporta la chiusura di tutti i file aperti, compresi tutti i
-socket relativi a connessioni stabilite; questo significa che al momento del
-crollo del servizio il client riceverà un FIN dal server in corrispondenza
-della chiusura del socket.
-
-
-
-
-
-%%% Local Variables:
-%%% mode: latex
-%%% TeX-master: "gapil"
-%%% End:
--- /dev/null
+%% tcpsock.tex
+%%
+%% Copyright (C) 2000-2003 Simone Piccardi. Permission is granted to
+%% copy, distribute and/or modify this document under the terms of the GNU Free
+%% Documentation License, Version 1.1 or any later version published by the
+%% Free Software Foundation; with the Invariant Sections being "Prefazione",
+%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the
+%% license is included in the section entitled "GNU Free Documentation
+%% License".
+%%
+\chapter{Socket TCP}
+\label{cha:TCP_socket}
+
+In questo capitolo iniziamo ad approfondire la conoscenza dei socket TCP,
+iniziando con una descrizione delle principali caratteristiche del
+funzionamento di una connessione TCP. Tratteremo poi le varie funzioni che
+servono alla creazione di una connessione fra un server elementare ed il suo
+client, fornendo poi alcuni esempi di applicazione elementare.
+
+
+
+\section{Il funzionamento di una connessione TCP}
+\label{sec:TCP_connession}
+
+Prima di entrare nei dettagli delle singole funzioni usate nelle applicazioni
+che utilizzano i socket TCP, è fondamentale spiegare alcune delle basi del
+funzionamento del protocollo, poiché questa conoscenza è essenziale per
+comprendere il comportamento di dette funzioni per questo tipo di socket, ed
+il relativo modello di programmazione.
+
+Si ricordi che il protocollo TCP serve a creare degli \textit{stream socket},
+cioè una forma di canale di comunicazione che stabilisce una connessione
+stabile fra due stazioni, in modo che queste possano scambiarsi dei dati. In
+questa sezione ci concentreremo sulle modalità con le quali il protocollo dà
+inizio e conclude una connessione e faremo inoltre un breve accenno al
+significato di alcuni dei vari \textsl{stati} ad essa associati.
+
+\subsection{La creazione della connessione: il \textit{three way handshake}}
+\label{sec:TCP_conn_cre}
+
+Il processo che porta a creare una connessione TCP è chiamato \textit{three
+ way handshake}; la successione tipica degli eventi (e dei
+\textsl{segmenti}\footnote{Si ricordi che il segmento è l'unità elementare di
+ dati trasmessa dal protocollo TCP al livello successivo; tutti i segmenti
+ hanno un header che contiene le informazioni che servono allo \textit{stack
+ TCP} (così viene di solito chiamata la parte del kernel che implementa il
+ protocollo) per realizzare la comunicazione, fra questi dati ci sono una
+ serie di flag usati per gestire la connessione, come SYN, ACK, URG, FIN,
+ alcuni di essi, come SYN (che sta per \textit{syncronize}) corrispondono a
+ funzioni particolari del protocollo e danno il nome al segmento, (per
+ maggiori dettagli vedere \secref{sec:tcp_protocol}).} di dati che vengono
+scambiati) che porta alla creazione di una connessione è la seguente:
+
+\begin{enumerate}
+\item Il server deve essere preparato per accettare le connessioni in arrivo;
+ il procedimento si chiama \textsl{apertura passiva} del socket (in inglese
+ \textit{passive open}). Questo viene fatto chiamando la sequenza di funzioni
+ \func{socket}, \func{bind} e \func{listen}. Completata l'apertura passiva il
+ server chiama la funzione \func{accept} e il processo si blocca in attesa di
+ connessioni.
+
+\item Il client richiede l'inizio della connessione usando la funzione
+ \func{connect}, attraverso un procedimento che viene chiamato
+ \textsl{apertura attiva}, dall'inglese \textit{active open}. La chiamata di
+ \func{connect} blocca il processo e causa l'invio da parte del client di un
+ segmento SYN, in sostanza viene inviato al server un pacchetto IP che
+ contiene solo gli header IP e TCP (con il numero di sequenza iniziale e il
+ flag SYN) e le opzioni di TCP.
+
+\item il server deve dare ricevuto (l'\textit{acknowledge}) del SYN del
+ client, inoltre anche il server deve inviare il suo SYN al client (e
+ trasmettere il suo numero di sequenza iniziale) questo viene fatto
+ ritrasmettendo un singolo segmento in cui sono impostati entrambi i flag SYN
+ e ACK.
+
+\item una volta che il client ha ricevuto l'acknowledge dal server la funzione
+ \func{connect} ritorna, l'ultimo passo è dare dare il ricevuto del SYN del
+ server inviando un ACK. Alla ricezione di quest'ultimo la funzione
+ \func{accept} del server ritorna e la connessione è stabilita.
+\end{enumerate}
+
+Il procedimento viene chiamato \textit{three way handshake} dato che per
+realizzarlo devono essere scambiati tre segmenti. In \figref{fig:TCP_TWH}
+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
+% l'equivalente di avere un telefono. La funzione \texttt{bind} è analoga al
+% dire alle altre persone qual'è il proprio numero di telefono perché possano
+% chiamare. La funzione \texttt{listen} è accendere il campanello del telefono
+% per sentire le chiamate in arrivo. La funzione \texttt{connect} richiede di
+% conoscere il numero di chi si vuole chiamare. La funzione \texttt{accept} è
+% quando si risponde al telefono.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=10cm]{img/three_way_handshake}
+ \caption{Il \textit{three way handshake} del TCP.}
+ \label{fig:TCP_TWH}
+\end{figure}
+
+Si è accennato in precedenza ai \textsl{numeri di sequenza} (che sono anche
+riportati in \figref{fig:TCP_TWH}): 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
+\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 impostando
+il flag 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
+è sempre pari al numero di sequenza iniziale incrementato di uno; lo stesso
+varrà anche (vedi \figref{fig:TCP_close}) per l'acknowledgement di un FIN.
+
+\subsection{Le opzioni TCP.}
+\label{sec:TCP_TCP_opt}
+
+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}, dove MMS sta per \textit{maximum segment size}, con
+ questa opzione ciascun capo della connessione annuncia all'altro il massimo
+ ammontare di dati che vorrebbe accettare per ciascun segmento nella
+ connessione corrente. È possibile leggere e scrivere questo valore
+ attraverso l'opzione del socket \const{TCP\_MAXSEG}.
+
+\item \textit{window scale option}, %come spiegato in \secref{sec:tcp_protocol}
+ il protocollo TCP implementa il controllo di flusso attraverso una
+ \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'header, che così può
+ indicare un massimo di 65535 byte;\footnote{ Linux usa come massimo 32767
+ per evitare problemi con alcune implementazioni che usano l'aritmetica con
+ segno per implementare lo stack TCP.} ma alcuni tipi di connessione come
+ quelle ad alta velocità (sopra i 45Mbit/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
+ esiste questa opzione che indica un fattore di scala da applicare al valore
+ della finestra annunciata\footnote{essendo una nuova opzione per garantire
+ la compatibilità con delle vecchie implementazioni del protocollo la
+ procedura che la attiva prevede come negoziazione che l'altro capo della
+ 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 spostare a sinistra il valore
+ 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
+ dovute a pacchetti perduti che riappaiono; anche questa viene negoziata come
+ la precedente.
+
+\end{itemize}
+
+La MSS è generalmente supportata da quasi tutte le implementazioni del
+protocollo, le ultime due opzioni (trattate
+nell'\href{http://www.ietf.org/rfc/rfc1323.txt}{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. In ogni caso Linux supporta pienamente entrambe le opzioni.
+
+\subsection{La terminazione della connessione}
+\label{sec:TCP_conn_term}
+
+Mentre per la creazione di una connessione occorre un interscambio di tre
+segmenti, la procedura di chiusura ne richiede normalmente quattro. In questo
+caso la successione degli eventi è la seguente:
+
+\begin{enumerate}
+\item Un processo ad uno dei due capi chiama la funzione \func{close}, dando
+ l'avvio a quella che viene chiamata \textsl{chiusura attiva} (o
+ \textit{active close}). Questo comporta l'emissione di un segmento FIN, che
+ serve ad indicare che si è finito con l'invio dei dati sulla connessione.
+
+\item L'altro capo della connessione riceve il FIN e dovrà eseguire la
+ \textsl{chiusura passiva} (o \textit{passive close}). Al FIN, come ad ogni
+ altro pacchetto, viene risposto con un ACK, inoltre il ricevimento del FIN
+ viene segnalato al processo che ha aperto il socket (dopo che ogni altro
+ eventuale dato rimasto in coda è stato ricevuto) come un end-of-file sulla
+ lettura: questo perché il ricevimento di un FIN significa che non si
+ riceveranno altri dati sulla connessione.
+
+\item Una volta rilevata l'end-of-file anche il secondo processo chiamerà la
+ funzione \func{close} sul proprio socket, causando l'emissione di un altro
+ segmento FIN.
+
+\item L'altro capo della connessione riceverà il FIN conclusivo e risponderà
+ con un ACK.
+\end{enumerate}
+
+Dato che in questo caso sono richiesti un FIN ed un ACK per ciascuna direzione
+normalmente i segmenti scambiati sono quattro. Questo non è vero sempre
+giacché in alcune situazioni il FIN del passo 1) è inviato insieme a dei dati.
+Inoltre è possibile che i segmenti inviati nei passi 2 e 3 dal capo che
+effettua la chiusura passiva, siano accorpati in un singolo segmento. In
+\figref{fig:TCP_close} si è rappresentato graficamente lo sequenza di
+scambio dei segmenti che conclude la connessione.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=10cm]{img/tcp_close}
+ \caption{La chiusura di una connessione TCP.}
+ \label{fig:TCP_close}
+\end{figure}
+
+Come per il SYN anche il FIN occupa un byte nel numero di sequenza, per cui
+l'ACK riporterà un \textit{acknowledge number} incrementato di uno.
+
+Si noti che, nella sequenza di chiusura, fra i passi 2 e 3, è in teoria
+possibile che si mantenga un flusso di dati dal capo della connessione che
+deve ancora eseguire la chiusura passiva a quello che sta eseguendo la
+chiusura attiva. Nella sequenza indicata i dati verrebbero persi, dato che si
+è chiuso il socket dal lato che esegue la chiusura attiva; esistono tuttavia
+situazioni in cui si vuole poter sfruttare questa possibilità, usando una
+procedura che è chiamata \textit{half-close}; torneremo su questo aspetto e su
+come utilizzarlo in \secref{xxx_shutdown}, quando parleremo della funzione
+\func{shutdown}.
+
+La emissione del FIN avviene quando il socket viene chiuso, questo però non
+avviene solo per la chiamata esplicita della funzione \func{close}, ma anche
+alla terminazione di un processo, quando tutti i file vengono chiusi. Questo
+comporta ad esempio che se un processo viene terminato da un segnale tutte le
+connessioni aperte verranno chiuse.
+
+Infine occorre sottolineare che, benché nella figura (e nell'esempio che
+vedremo più avanti in \secref{sec:TCP_echo}) sia stato il client ad eseguire
+la chiusura attiva, nella realtà questa può essere eseguita da uno qualunque
+dei due capi della comunicazione (come nell'esempio di
+\figref{fig:TCP_daytime_iter_server_code}), e anche se il caso più comune
+resta quello del client, 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:TCP_conn_dia}
+
+Come abbiamo visto le operazioni del TCP nella creazione e conclusione di una
+connessione sono piuttosto complesse, ed abbiamo esaminato soltanto quelle
+relative ad un andamento normale. In \secref{sec:TCP_states} vedremo con
+maggiori dettagli che una connessione può assumere vari stati, che ne
+caratterizzano il funzionamento, e che sono quelli che vengono riportati dal
+comando \cmd{netstat}, per ciascun socket TCP aperto, nel campo
+\textit{State}.
+
+Non possiamo affrontare qui una descrizione completa del funzionamento del
+protocollo; un approfondimento sugli aspetti principali si trova in
+\secref{sec:tcp_protocol}, ma per una trattazione completa il miglior
+riferimento resta \cite{TCPIll1}. 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 è \texttt{CLOSED}; quando una
+applicazione esegue una apertura attiva il TCP emette un SYN e lo stato
+diventa \texttt{SYN\_SENT}; quando il TCP riceve la risposta del SYN$+$ACK
+emette un ACK e passa allo stato \texttt{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 \texttt{CLOSED} allo
+stato \texttt{LISTEN} in cui vengono accettate le connessioni.
+
+Dallo stato \texttt{ESTABLISHED} si può uscire in due modi; se un'applicazione
+chiama la funzione \texttt{close} prima di aver ricevuto un
+\textit{end-of-file} (chiusura attiva) la transizione è verso lo stato
+\texttt{FIN\_WAIT\_1}; se invece l'applicazione riceve un FIN nello stato
+\texttt{ESTABLISHED} (chiusura passiva) la transizione è verso lo stato
+\texttt{CLOSE\_WAIT}.
+
+In \figref{fig:TCP_conn_example} è 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
+ \includegraphics[width=9cm]{img/tcp_connection}
+ \caption{Schema dello scambio di pacchetti per un esempio di connessione.}
+ \label{fig:TCP_conn_example}
+\end{figure}
+
+La connessione viene iniziata dal client che annuncia un MSS di 1460, un
+valore tipico con Linux per IPv4 su Ethernet, 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 byte 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 \secref{sec:TCP_conn_term}; si noti che il capo della
+connessione che esegue la chiusura attiva entra nello stato
+\texttt{TIME\_WAIT}, sul cui significato 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:TCP_time_wait}
+
+Come riportato da Stevens in \cite{UNP1} lo stato \texttt{TIME\_WAIT} è
+probabilmente uno degli aspetti meno compresi del protocollo TCP, è infatti
+comune trovare 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 \figref{fig:TCP_conn_example})
+\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 \secref{sec:IP_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 ``\textsl{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'\href{http://www.ietf.org/rfc/rfc1122.txt}{RFC~1122} raccomanda 2 minuti,
+Linux usa 30 secondi), questo comporta una durata dello stato
+\texttt{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{enumerate}
+\item implementare in maniera affidabile la terminazione della connessione
+ in entrambe le direzioni.
+\item consentire l'eliminazione dei segmenti duplicati dalla rete.
+\end{enumerate}
+
+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
+\figref{fig:TCP_conn_example}: assumendo che l'ultimo ACK della sequenza
+(quello del capo che ha eseguito la chiusura attiva) vanga perso, chi esegue
+la chiusura passiva non ricevendo 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 un socket deve rimanere attivo nello stato \texttt{TIME\_WAIT} anche
+dopo l'invio dell'ultimo ACK, per potere essere in grado di gestirne
+l'eventuale ritrasmissione, in caso esso venga perduto.
+
+Il secondo motivo è più complesso da capire, e necessita di una spiegazione
+degli scenari in cui può accadere che i pacchetti TCP si possano perdere nella
+rete o restare intrappolati, per poi riemergere in un secondo tempo.
+
+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 tempo (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 TCP, chi l'ha inviato,
+non ricevendo un ACK in 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, dato che
+altrimenti verrebbe ecceduto il TTL) l'anomalia viene a cessare, il circolo di
+instradamento 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 \texttt{195.110.112.236} porta 1550 e l'IP
+\texttt{192.84.145.100} porta 22 (affronteremo il significato delle porte
+nella prossima sezione), 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 per le risposte nella direzione opposta.
+
+In questo modo, prima che venga creata una nuova connessione, il protocollo
+TCP si assicura che tutti gli eventuali segmenti residui di una precedente
+connessione, che potrebbero causare disturbi, siano stati eliminati dalla
+rete.
+
+
+\subsection{I numeri di porta}
+\label{sec:TCP_port_num}
+
+In un ambiente multitasking in un dato momento più processi devono poter 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
+\secref{sec:sock_sa_ipv4} e \secref{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 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'\href{http://www.ietf.org/rfc/rfc1700.txt}{RFC~1700} che contiene
+l'elenco delle porte assegnate dalla IANA (la \textit{Internet Assigned Number
+ Authority}) ma l'elenco viene costantemente aggiornato e pubblicato su
+internet (una versione aggiornata si può trovare all'indirizzo
+\texttt{ftp://ftp.isi.edu/in-notes/iana/assignements/port-numbers}); inoltre
+in un sistema unix-like un analogo elenco viene mantenuto nel file
+\file{/etc/services}, con la corrispondenza fra i vari 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'\href{http://www.ietf.org/rfc/rfc1700.txt}{RFC~1700} i vari sistemi hanno
+fatto scelte diverse per le porte effimere, in particolare in
+\figref{fig:TCP_port_alloc} sono riportate quelle di BSD e Linux. Nel caso di
+Linux poi la scelta fra i due intervalli possibili viene fatta dinamicamente a
+seconda della memoria a disposizione del kernel per gestire le relative
+tabelle.
+
+\begin{figure}[!htb]
+ \centering
+ \includegraphics[width=15cm]{img/port_alloc}
+ \caption{Allocazione dei numeri di porta.}
+ \label{fig:TCP_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 amministratore, per far si che
+solo l'amministratore possa allocare queste porte per far partire i relativi
+servizi.
+
+Si tenga conto poi che ci sono alcuni client, in particolare \cmd{rsh} e
+\cmd{rlogin}, che richiedono una connessione su una porta riservata anche dal
+lato client come parte dell'autenticazione, contando appunto sul fatto che
+solo l'amministratore può usare queste porte. Data l'assoluta inconsistenza in
+termini di sicurezza di un tale metodo, al giorno d'oggi esso è in completo
+disuso.
+
+Data una connessione TCP si suole chiamare \textit{socket pair}\footnote{da
+ non confondere con la coppia di socket della omonima funzione
+ \func{socketpair} che fanno riferimento ad una coppia di socket sulla stessa
+ macchina, non ai capi di una connessione TCP.} 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
+(\texttt{195.110.112.152:22}, \texttt{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 \cmd{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:TCP_port_cliserv}
+
+Per capire meglio l'uso delle porte e come vengono utilizzate quando si ha a
+che fare con un'applicazione client/server (come quelle che descriveremo in
+\secref{sec:TCP_daytime_application} e \secref{sec:TCP_echo_application})
+esamineremo cosa accade con le connessioni nel caso di un server TCP che deve
+gestire connessioni multiple.
+
+Se eseguiamo un \cmd{netstat} su una macchina di prova (il cui indirizzo sia
+\texttt{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 e attivi 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 interfacce locali. La notazione \texttt{0.0.0.0} usata da
+\cmd{netstat} è equivalente all'asterisco utilizzato per il numero di porta,
+indica il valore generico, e corrisponde al valore \const{INADDR\_ANY}
+definito in \file{arpa/inet.h} (vedi \ref{tab:TCP_ipv4_addr}).
+
+Inoltre si noti come la porta e l'indirizzo di ogni eventuale connessione
+esterna non sono specificati; in questo caso la \textit{socket pair} associata
+al socket potrebbe essere indicata come (\texttt{*:22}, \texttt{*:*}), usando
+anche per gli indirizzi l'asterisco come carattere che indica il valore
+generico.
+
+Dato che in genere una macchina è associata ad un solo indirizzo IP, ci si può
+chiedere che senso abbia l'utilizzo dell'indirizzo generico per specificare
+l'indirizzo locale; ma a parte il caso di macchine che hanno più di un
+indirizzo IP (il cosiddetto \textit{multihoming}) esiste sempre anche
+l'indirizzo di loopback, per cui con l'uso dell'indirizzo generico si possono
+accettare connessioni indirizzate verso uno qualunque degli indirizzi IP
+presenti. Ma, come si può vedere nell'esempio con il DNS che è in ascolto
+sulla porta 53, è possibile anche restringere l'accesso ad 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, per esempio
+quella con l'indirizzo \texttt{192.84.146.100}, si dovrà lanciare su
+quest'ultima un client \cmd{ssh} per creare una connessione, e il kernel gli
+assocerà una porta effimera (ad esempio la 21100), per cui la connessione sarà
+espressa dalla socket pair (\texttt{192.84.146.100:21100},
+\texttt{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 \cmd{netstat} otteniamo 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 utilizza anch'esso
+la porta 22, ed ha specificato l'indirizzo locale, questo è il socket con cui
+il processo figlio gestisce la connessione mentre il padre resta in ascolto
+sul socket originale.
+
+Se a questo punto lanciamo un'altra volta il client \cmd{ssh} per una seconda
+connessione quello che otterremo usando \cmd{netstat} 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è il client effettuerà la connessione usando un'altra porta effimera: con
+questa sarà aperta la connessione, ed il server creerà un'altro processo
+figlio per gestirla.
+
+Tutto ciò mostra come il TCP, per poter gestire le connessioni con un server
+concorrente, 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\footnote{ad esempio con il comando \cmd{fuser}, o con \cmd{lsof}.} 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{Le funzioni di base per la gestione dei socket}
+\label{sec:TCP_functions}
+
+In questa sezione descriveremo in maggior dettaglio le varie funzioni che
+vengono usate per la gestione di base dei socket TCP, non torneremo però sulla
+funzione \func{socket}, che è già stata esaminata accuratamente nel capitolo
+precedente in \secref{sec:sock_socket}.
+
+
+\subsection{La funzione \func{bind}}
+\label{sec:TCP_func_bind}
+
+La funzione \funcd{bind} assegna un indirizzo locale ad un socket. È usata
+cioè per specificare la prima parte dalla socket pair. Viene usata sul lato
+server per specificare la porta (e gli eventuali indirizzi locali) su cui poi
+ci si porrà in ascolto. Il prototipo della funzione è il seguente:
+\begin{prototype}{sys/socket.h}
+{int bind(int sockfd, const struct sockaddr *serv\_addr, socklen\_t addrlen)}
+
+ Assegna un indirizzo ad un socket.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore;
+ in caso di errore la variabile \var{errno} viene impostata secondo i
+ seguenti codici di errore:
+ \begin{errlist}
+ \item[\errcode{EBADF}] il file descriptor non è valido.
+ \item[\errcode{EINVAL}] il socket ha già un indirizzo assegnato.
+ \item[\errcode{ENOTSOCK}] il file descriptor non è associato ad un socket.
+ \item[\errcode{EACCES}] si è cercato di usare una porta riservata senza
+ sufficienti privilegi.
+ \item[\errcode{EADDRNOTAVAIL}] Il tipo di indirizzo specificato non è
+ disponibile.
+ \item[\errcode{EADDRINUSE}] qualche altro socket sta già usando l'indirizzo.
+ \end{errlist}
+ ed anche \errval{EFAULT} e per i socket di tipo \const{AF\_UNIX},
+ \errval{ENOTDIR}, \errval{ENOENT}, \errval{ENOMEM}, \errval{ELOOP},
+ \errval{ENOSR} e \errval{EROFS}.}
+\end{prototype}
+
+Il primo argomento è un file descriptor ottenuto da una precedente chiamata a
+\func{socket}, mentre il secondo e terzo argomento sono rispettivamente
+l'indirizzo (locale) del socket e la dimensione della struttura che lo
+contiene, secondo quanto già trattato in \secref{sec:sock_sockaddr}.
+
+Con i socket TCP la chiamata \func{bind} permette di specificare l'indirizzo,
+la porta, entrambi o nessuno dei due. In genere i server utilizzano una porta
+nota che assegnano all'avvio, se questo non viene fatto è il kernel a
+scegliere una porta effimera quando vengono eseguite la funzioni
+\func{connect} o \func{listen}, ma se questo è normale per il client non lo è
+per il server\footnote{un'eccezione a tutto ciò sono i server che usano RPC.
+ In questo caso viene fatta assegnare dal kernel una porta effimera che poi
+ viene registrata presso il \textit{portmapper}; quest'ultimo è un altro
+ demone che deve essere contattato dai client per ottenere la porta effimera
+ su cui si trova il server.} che in genere viene identificato dalla porta su
+cui risponde (l'elenco di queste porte, e dei relativi servizi, è in
+\file{/etc/services}).
+
+Con \func{bind} si può assegnare un IP specifico ad un socket, purché questo
+appartenga ad una interfaccia della macchina. Per un client TCP questo
+diventerà l'indirizzo sorgente usato per i tutti i pacchetti inviati sul
+socket, mentre per un server TCP questo restringerà l'accesso al socket solo
+alle connessioni che arrivano verso tale indirizzo.
+
+Normalmente un client non specifica mai l'indirizzo di un socket, ed il kernel
+sceglie l'indirizzo di origine quando viene effettuata la connessione, sulla
+base dell'interfaccia usata per trasmettere i pacchetti, (che dipenderà dalle
+regole di instradamento usate per raggiungere il server). Se un server non
+specifica il suo indirizzo locale il kernel userà come indirizzo di origine
+l'indirizzo di destinazione specificato dal SYN del client.
+
+Per specificare un indirizzo generico, con IPv4 si usa il valore
+\const{INADDR\_ANY}, il cui valore, come accennato in
+\secref{sec:sock_sa_ipv4}, è pari a zero; nell'esempio
+\figref{fig:TCP_daytime_iter_server_code} si è usata un'assegnazione immediata
+del tipo: \includecodesnip{listati/serv_addr_sin_addr.c}
+
+Si noti che si è usato \func{htonl} per assegnare il valore
+\const{INADDR\_ANY}, anche se, essendo questo nullo, il riordinamento è
+inutile. Si tenga presente comunque che tutte le costanti \val{INADDR\_}
+(riportate in \tabref{tab:TCP_ipv4_addr}) sono definite secondo
+l'\textit{endianess} della macchina, ed anche se esse possono essere
+invarianti rispetto all'ordinamento dei bit, è comunque buona norma usare
+sempre la funzione \func{htonl}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Costante} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{INADDR\_ANY} & Indirizzo generico (\texttt{0.0.0.0})\\
+ \const{INADDR\_BROADCAST}& Indirizzo di \textit{broadcast}.\\
+ \const{INADDR\_LOOPBACK} & Indirizzo di \textit{loopback}
+ (\texttt{127.0.0.1}).\\
+ \const{INADDR\_NONE} & Indirizzo errato.\\
+ \hline
+ \end{tabular}
+ \caption{Costanti di definizione di alcuni indirizzi generici per IPv4.}
+ \label{tab:TCP_ipv4_addr}
+\end{table}
+
+L'esempio precedente funziona correttamente con IPv4 poiché che l'indirizzo è
+rappresentabile anche con un intero a 32 bit; non si può usare lo stesso
+metodo con IPv6, in cui l'indirizzo deve necessariamente essere specificato
+con una struttura, perché il linguaggio C non consente l'uso di una struttura
+costante come operando a destra in una assegnazione.
+
+Per questo motivo nell'header \file{netinet/in.h} è definita una variabile
+\const{in6addr\_any} (dichiarata come \direct{extern}, ed inizializzata dal
+sistema al valore \const{IN6ADRR\_ANY\_INIT}) che permette di effettuare una
+assegnazione del tipo: \includecodesnip{listati/serv_addr_sin6_addr.c} in
+maniera analoga si può utilizzare la variabile \const{in6addr\_loopback} per
+indicare l'indirizzo di \textit{loopback}, che a sua volta viene inizializzata
+staticamente a \const{IN6ADRR\_LOOPBACK\_INIT}.
+
+
+
+\subsection{La funzione \func{connect}}
+\label{sec:TCP_func_connect}
+
+La funzione \funcd{connect} è usata da un client TCP per stabilire la
+connessione con un server TCP, il prototipo della funzione è il seguente:
+\begin{prototype}{sys/socket.h}
+{int connect(int sockfd, const struct sockaddr *servaddr, socklen\_t addrlen)}
+
+ Stabilisce una connessione fra due socket.
+
+ \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{ECONNREFUSED}] non c'è nessuno in ascolto sull'indirizzo
+ remoto.
+ \item[\errcode{ETIMEDOUT}] si è avuto timeout durante il tentativo di
+ connessione.
+ \item[\errcode{ENETUNREACH}] la rete non è raggiungibile.
+ \item[\errcode{EINPROGRESS}] il socket è non bloccante (vedi
+ \secref{sec:file_noblocking}) e la connessione non può essere conclusa
+ immediatamente.
+ \item[\errcode{EALREADY}] il socket è non bloccante (vedi
+ \secref{sec:file_noblocking}) e un tentativo precedente di connessione non
+ si è ancora concluso.
+ \item[\errcode{EAGAIN}] non ci sono più porte locali libere.
+ \item[\errcode{EAFNOSUPPORT}] l'indirizzo non ha una famiglia di indirizzi
+ corretta nel relativo campo.
+ \item[\errcode{EACCES}, \errcode{EPERM}] si è tentato di eseguire una
+ connessione ad un indirizzo broadcast senza che il socket fosse stato
+ abilitato per il broadcast.
+ \end{errlist}
+ altri errori possibili sono: \errval{EFAULT}, \errval{EBADF},
+ \errval{ENOTSOCK}, \errval{EISCONN} e \errval{EADDRINUSE}.}
+\end{prototype}
+
+Il primo argomento è un file descriptor ottenuto da una precedente chiamata a
+\func{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 \secref{sec:sock_sockaddr}.
+
+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 \secref{sec:TCP_daytime_client}, usando le funzioni illustrate in
+\secref{sec:sock_addr_func}.
+
+Nel caso di socket TCP la funzione \func{connect} avvia il \textit{three way
+ handshake}, e ritorna solo quando la connessione è stabilita o si è
+verificato un errore. Le possibili cause di errore sono molteplici (ed i
+relativi codici riportati sopra), quelle che però dipendono dalla situazione
+della rete e non da errori o problemi nella chiamata della funzione sono le
+seguenti:
+\begin{enumerate}
+\item Il client non riceve risposta al SYN: l'errore restituito è
+ \errcode{ETIMEDOUT}. Stevens riporta che BSD invia un primo SYN alla chiamata
+ di \func{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
+ \func{sysctl} che attraverso il filesystem \file{/proc} scrivendo il valore
+ voluto in \file{/proc/sys/net/ipv4/tcp\_syn\_retries}. Il valore predefinito
+ per la ripetizione dell'invio è di 5 volte, che comporta un timeout dopo
+ circa 180 secondi.
+%
+% Le informazioni su tutte le opzioni impostabili via /proc stanno in
+% Linux/Documentation/networking/ip-sysctl.txt
+%
+\item 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 probabilmente 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
+ \errcode{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, quando 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. In questo caso dato che il messaggio può
+ essere dovuto ad una condizione transitoria si ripete l'emissione dei SYN
+ come nel caso precedente, fino al timeout, e solo allora si restituisce il
+ codice di errore dovuto al messaggio ICMP, che da luogo ad un
+ \errcode{ENETUNREACH}.
+
+\end{enumerate}
+
+Se si fa riferimento al diagramma degli stati del TCP riportato in
+\figref{fig:TCP_state_diag} la funzione \func{connect} porta un socket
+dallo stato \texttt{CLOSED} (lo stato iniziale in cui si trova un socket
+appena creato) prima allo stato \texttt{SYN\_SENT} e poi, al ricevimento del
+ACK, nello stato \texttt{ESTABLISHED}. Se invece la connessione fallisce il
+socket non è più utilizzabile e deve essere chiuso.
+
+Si noti infine che con la funzione \func{connect} si è specificato solo
+indirizzo e porta del server, quindi solo una metà della socket pair; essendo
+questa funzione usata nei client l'altra metà contenente indirizzo e porta
+locale viene lasciata all'assegnazione automatica del kernel, e non è
+necessario effettuare una \func{bind}.
+
+
+\subsection{La funzione \func{listen}}
+\label{sec:TCP_func_listen}
+
+La funzione \funcd{listen} serve ad usare un socket in modalità passiva, cioè,
+come dice il nome, per metterlo in ascolto di eventuali connessioni; in
+sostanza l'effetto della funzione è di portare il socket dallo stato
+\texttt{CLOSED} a quello \texttt{LISTEN}. In genere si chiama la funzione in
+un server dopo le chiamate a \func{socket} e \func{bind} e prima della
+chiamata ad \func{accept}. Il prototipo della funzione, come definito dalla
+pagina di manuale, è:
+\begin{prototype}{sys/socket.h}{int listen(int sockfd, int backlog)}
+ Pone un socket in attesa di una connessione.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore. I codici di errore restituiti in \var{errno} sono i seguenti:
+ \begin{errlist}
+ \item[\errcode{EBADF}] l'argomento \param{sockfd} non è un file descriptor
+ valido.
+ \item[\errcode{ENOTSOCK}] l'argomento \param{sockfd} non è un socket.
+ \item[\errcode{EOPNOTSUPP}] il socket è di un tipo che non supporta questa
+ operazione.
+ \end{errlist}}
+\end{prototype}
+
+La funzione pone il socket specificato da \param{sockfd} in modalità passiva e
+predispone una coda per le connessioni in arrivo di lunghezza pari a
+\param{backlog}. La funzione si può applicare solo a socket di tipo
+\const{SOCK\_STREAM} o \const{SOCK\_SEQPACKET}.
+
+L'argomento \param{backlog} indica il numero massimo di connessioni pendenti
+accettate; se esso viene ecceduto il client al momento della richiesta della
+connessione riceverà un errore di tipo \errcode{ECONNREFUSED}, o se il
+protocollo, come accade nel caso del TCP, supporta la ritrasmissione, la
+richiesta sarà ignorata in modo che la connessione possa venire ritentata.
+
+Per capire meglio il significato di tutto ciò occorre approfondire la modalità
+con cui il kernel tratta le connessioni in arrivo. Per ogni socket in ascolto
+infatti vengono mantenute due code:
+\begin{enumerate}
+\item La coda delle connessioni incomplete (\textit{incomplete connection
+ queue} che contiene un riferimento per ciascun socket per il quale è
+ arrivato un SYN ma il \textit{three way handshake} non si è ancora concluso.
+ Questi socket sono tutti nello stato \texttt{SYN\_RECV}.
+\item La coda delle connessioni complete (\textit{complete connection queue}
+ che contiene un ingresso per ciascun socket per il quale il three way
+ handshake è stato completato ma ancora \func{accept} non è ritornata.
+ Questi socket sono tutti nello stato \texttt{ESTABLISHED}.
+\end{enumerate}
+
+Lo schema di funzionamento è descritto in \figref{fig:TCP_listen_backlog}:
+quando arriva un SYN da un client il server crea una nuova voce nella coda
+delle connessioni incomplete, e poi risponde con il SYN$+$ACK. La voce resterà
+nella coda delle connessioni incomplete fino al ricevimento dell'ACK dal
+client o fino ad un timeout. Nel caso di completamento del three way handshake
+la voce viene spostata nella coda delle connessioni complete. Quando il
+processo chiama la funzione \func{accept} (vedi \secref{sec:TCP_func_accept})
+la prima voce nella coda delle connessioni complete è passata al programma, o,
+se la coda è vuota, il processo viene posto in attesa e risvegliato all'arrivo
+della prima connessione completa.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=11cm]{img/tcp_listen_backlog}
+ \caption{Schema di funzionamento delle code delle connessioni complete ed
+ incomplete.}
+ \label{fig:TCP_listen_backlog}
+\end{figure}
+
+Storicamente il valore del parametro \param{backlog} era corrispondente al
+massimo valore della somma del numero di voci possibili per ciascuna delle due
+code. Stevens in \cite{UNP1} riporta che BSD ha sempre applicato un fattore di
+1.5 a detto valore, e fornisce una tabella con i risultati ottenuti con vari
+kernel, compreso Linux 2.0, che mostrano le differenze fra diverse
+implementazioni.
+
+In Linux il significato di questo valore è cambiato a partire dal kernel 2.2
+per prevenire l'attacco chiamato \textit{syn flood}. Questo si basa
+sull'emissione da parte dell'attaccante di un grande numero di pacchetti SYN
+indirizzati verso una porta, forgiati con indirizzo IP fasullo\footnote{con la
+ tecnica che viene detta \textit{ip spoofing}.} così che i SYN$+$ACK vanno
+perduti e la coda delle connessioni incomplete viene saturata, impedendo di
+fatto ulteriori connessioni.
+
+Per ovviare a questo il significato del \param{backlog} è stato cambiato a
+indicare la lunghezza della coda delle connessioni complete. La lunghezza
+della coda delle connessioni incomplete può essere ancora controllata usando
+la funzione \func{sysctl} con il parametro \const{NET\_TCP\_MAX\_SYN\_BACKLOG}
+o scrivendola direttamente in
+\file{/proc/sys/net/ipv4/tcp\_max\_syn\_backlog}. Quando si attiva la
+protezione dei syncookies però (con l'opzione da compilare nel kernel e da
+attivare usando \file{/proc/sys/net/ipv4/tcp\_syncookies}) questo valore viene
+ignorato e non esiste più un valore massimo. In ogni caso in Linux il valore
+di \param{backlog} viene troncato ad un massimo di \const{SOMAXCONN} se è
+superiore a detta costante (che di default vale 128).
+
+La scelta storica per il valore di questo parametro era di 5, e alcuni vecchi
+kernel non supportavano neanche valori superiori, ma la situazione corrente è
+molto cambiata per via della presenza di server web che devono gestire un gran
+numero di connessioni per cui un tale valore non è più adeguato. Non esiste
+comunque una risposta univoca per la scelta del valore, per questo non
+conviene specificarlo con una costante (il cui cambiamento richiederebbe la
+ricompilazione del server) ma usare piuttosto una variabile di ambiente (vedi
+\secref{sec:proc_environ}).
+
+Stevens tratta accuratamente questo argomento in \cite{UNP1}, con esempi presi
+da casi reali su web server, ed in particolare evidenzia come non sia più vero
+che il compito principale della coda sia quello di gestire il caso in cui il
+server è occupato fra chiamate successive alla \func{accept} (per cui la coda
+più occupata sarebbe quella delle connessioni completate), ma piuttosto quello
+di gestire la presenza di un gran numero di SYN in attesa di concludere il
+three way handshake.
+
+Infine va messo in evidenza che, nel caso di socket TCP, quando un SYN arriva
+con tutte le code piene, il pacchetto deve essere ignorato. Questo perché la
+condizione in cui le code sono piene è ovviamente transitoria, per cui se il
+client ritrasmette il SYN è probabile che passato un po' di tempo possa
+trovare nella coda lo spazio per una nuova connessione. Se invece si
+rispondesse con un RST, per indicare l'impossibilità di effettuare la
+connessione, la chiamata a \func{connect} nel client ritornerebbe con una
+condizione di errore, costringendo a inserire nell'applicazione la gestione
+dei tentativi di riconnessione, che invece può essere effettuata in maniera
+trasparente dal protocollo TCP.
+
+
+\subsection{La funzione \func{accept}}
+\label{sec:TCP_func_accept}
+
+La funzione \funcd{accept} è chiamata da un server per gestire la connessione
+una volta che sia stato completato il \textit{three way handshake}, la
+funzione restituisce un nuovo socket descriptor su cui si potrà operare per
+effettuare la comunicazione. Se non ci sono connessioni completate il processo
+viene messo in attesa. Il prototipo della funzione è il seguente:
+\begin{prototype}{sys/socket.h}
+{int accept(int sockfd, struct sockaddr *addr, socklen\_t *addrlen)}
+
+ Accetta una connessione sul socket specificato.
+
+ \bodydesc{La funzione restituisce un numero di socket descriptor positivo in
+ caso di successo e -1 in caso di errore, nel qual caso \var{errno} viene
+ impostata ai seguenti valori:
+
+ \begin{errlist}
+ \item[\errcode{EBADF}] l'argomento \param{sockfd} non è un file descriptor
+ valido.
+ \item[\errcode{ENOTSOCK}] l'argomento \param{sockfd} non è un socket.
+ \item[\errcode{EOPNOTSUPP}] il socket è di un tipo che non supporta questa
+ operazione.
+ \item[\errcode{EAGAIN} o \errcode{EWOULDBLOCK}] il socket è stato impostato
+ come non bloccante (vedi \secref{sec:file_noblocking}), e non ci sono
+ connessioni in attesa di essere accettate.
+ \item[\errcode{EPERM}] Le regole del firewall non consentono la connessione.
+ \item[\errcode{ENOBUFS}, \errcode{ENOMEM}] questo spesso significa che
+ l'allocazione della memoria è limitata dai limiti sui buffer dei socket,
+ non dalla memoria di sistema.
+ \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+ \end{errlist}
+ Inoltre possono essere restituiti gli errori di rete relativi al nuovo
+ socket, diversi a secondo del protocollo, come: \errval{EMFILE},
+ \errval{EINVAL}, \errval{ENOSR}, \errval{ENOBUFS}, \errval{EFAULT},
+ \errval{EPERM}, \errval{ECONNABORTED}, \errval{ESOCKTNOSUPPORT},
+ \errval{EPROTONOSUPPORT}, \errval{ETIMEDOUT}, \errval{ERESTARTSYS}.}
+\end{prototype}
+
+La funzione estrae la prima connessione relativa al socket \param{sockfd} in
+attesa sulla coda delle connessioni complete, che associa ad nuovo socket con
+le stesse caratteristiche di \param{sockfd}. Il socket originale non viene
+toccato e resta nello stato di \texttt{LISTEN}, mentre il nuovo socket viene
+posto nello stato \texttt{ESTABLISHED}. Nella struttura \param{addr} e nella
+variabile \param{addrlen} vengono restituiti indirizzo e relativa lunghezza
+del client che si è connesso.
+
+I due argomenti \param{addr} e \param{addrlen} (si noti che quest'ultimo è
+passato per indirizzo per avere indietro il valore) sono usati per ottenere
+l'indirizzo del client da cui proviene la connessione. Prima della chiamata
+\param{addrlen} deve essere inizializzato alle dimensioni della struttura il
+cui indirizzo è passato come argomento in \param{addr}; al ritorno della
+funzione \param{addrlen} conterrà il numero di byte scritti dentro
+\param{addr}. Se questa informazione non interessa basterà inizializzare a
+\val{NULL} detti puntatori.
+
+Se la funzione ha successo restituisce il descrittore di un nuovo socket
+creato dal kernel (detto \textit{connected socket}) a cui viene associata la
+prima connessione completa (estratta dalla relativa coda, vedi
+\secref{sec:TCP_func_listen}) che il client ha effettuato verso il socket
+\param{sockfd}. Quest'ultimo (detto \textit{listening socket}) è quello creato
+all'inizio e messo in ascolto con \func{listen}, e non viene toccato dalla
+funzione. Se non ci sono connessioni pendenti da accettare la funzione mette
+in attesa il processo\footnote{a meno che non si sia impostato il socket per
+ essere non bloccante (vedi \secref{sec:file_noblocking}), nel qual caso
+ ritorna con l'errore \errcode{EAGAIN}. Torneremo su questa modalità di
+ operazione in \secref{sec:xxx_sock_noblock}.} fintanto che non ne arriva
+una.
+
+La funzione può essere usata solo con socket che supportino la connessione
+(cioè di tipo \const{SOCK\_STREAM}, \const{SOCK\_SEQPACKET} o
+\const{SOCK\_RDM}). Per alcuni protocolli che richiedono una conferma
+esplicita della connessione,\footnote{attualmente in Linux solo DECnet ha
+ questo comportamento.} la funzione opera solo l'estrazione dalla coda delle
+connessioni, la conferma della connessione viene eseguita implicitamente dalla
+prima chiamata ad una \func{read} o una \func{write}, mentre il rifiuto della
+connessione viene eseguito con la funzione \func{close}.
+
+È da chiarire che Linux presenta un comportamento diverso nella gestione degli
+errori rispetto ad altre implementazioni dei socket BSD, infatti la funzione
+\func{accept} passa gli errori di rete pendenti sul nuovo socket come codici
+di errore per \func{accept}, per cui l'applicazione deve tenerne conto ed
+eventualmente ripetere la chiamata alla funzione come per l'errore di
+\errcode{EAGAIN} (torneremo su questo in \secref{sec:TCP_echo_critical}).
+Un'altra differenza con BSD è che la funzione non fa ereditare al nuovo socket
+i flag del socket originale, come \const{O\_NONBLOCK},\footnote{ed in generale
+ tutti quelli che si possono impostare con \func{fcntl}, vedi
+ \secref{sec:file_fcntl}.} che devono essere rispecificati ogni volta. Tutto
+questo deve essere tenuto in conto se si devono scrivere programmi portabili.
+
+Il meccanismo di funzionamento di \func{accept} è essenziale per capire il
+funzionamento di un server: in generale infatti c'è sempre un solo socket in
+ascolto, detto per questo \textit{listening socket}, che resta per tutto il
+tempo nello stato \texttt{LISTEN}, mentre le connessioni vengono gestite dai
+nuovi socket, detti \textit{connected socket}, ritornati da \func{accept}, che
+si trovano automaticamente nello stato \texttt{ESTABLISHED}, e vengono
+utilizzati per lo scambio dei dati, che avviene su di essi, fino alla chiusura
+della connessione. Si può riconoscere questo schema anche nell'esempio
+elementare di \figref{fig:TCP_daytime_iter_server_code}, dove per ogni
+connessione il socket creato da \func{accept} viene chiuso dopo l'invio dei
+dati.
+
+
+\subsection{Le funzioni \func{getsockname} e \func{getpeername}}
+\label{sec:TCP_get_names}
+
+Oltre a tutte quelle viste finora, dedicate all'utilizzo dei socket, esistono
+alcune funzioni ausiliarie che possono essere usate per recuperare alcune
+informazioni relative ai socket ed alle connessioni ad essi associate. Le due
+funzioni più elementari sono queste, che vengono usate per ottenere i dati
+relativi alla socket pair associata ad un certo socket.
+
+La prima funzione è \funcd{getsockname} e serve ad ottenere l'indirizzo locale
+associato ad un socket; il suo prototipo è:
+\begin{prototype}{sys/socket.h}
+ {int getsockname(int sockfd, struct sockaddr * name, socklen\_t * namelen)}
+ Legge l'indirizzo locale di un socket.
+
+\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore. I codici di errore restituiti in \var{errno} sono i seguenti:
+ \begin{errlist}
+ \item[\errcode{EBADF}] l'argomento \param{sockfd} non è un file descriptor
+ valido.
+ \item[\errcode{ENOTSOCK}] l'argomento \param{sockfd} non è un socket.
+ \item[\errcode{ENOBUFS}] non ci sono risorse sufficienti nel sistema per
+ eseguire l'operazione.
+ \item[\errcode{EFAULT}] l'indirizzo \param{name} non è valido.
+ \end{errlist}}
+\end{prototype}
+
+La funzione restituisce la struttura degli indirizzi del socket \param{sockfd}
+nella struttura indicata dal puntatore \param{name} la cui lunghezza è
+specificata tramite l'argomento \param{namlen}. Quest'ultimo viene passato
+come indirizzo per avere indietro anche il numero di byte effettivamente
+scritti nella struttura puntata da \param{name}. Si tenga presente che se si è
+utilizzato un buffer troppo piccolo per \param{name} l'indirizzo risulterà
+troncato.
+
+La funzione si usa tutte le volte che si vuole avere l'indirizzo locale di un
+socket; ad esempio può essere usata da un client (che usualmente non chiama
+\func{bind}) per ottenere numero IP e porta locale associati al socket
+restituito da una \func{connect}, o da un server che ha chiamato \func{bind}
+su un socket usando 0 come porta locale per ottenere il numero di porta
+effimera assegnato dal kernel.
+
+Inoltre quando un server esegue una \func{bind} su un indirizzo generico, se
+chiamata dopo il completamento di una connessione sul socket restituito da
+\func{accept}, restituisce l'indirizzo locale che il kernel ha assegnato a
+quella connessione.
+
+Tutte le volte che si vuole avere l'indirizzo remoto di un socket si usa la
+funzione \funcd{getpeername}, il cui prototipo è:
+\begin{prototype}{sys/socket.h}
+ {int getpeername(int sockfd, struct sockaddr * name, socklen\_t * namelen)}
+ Legge l'indirizzo remoto di un socket.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore. I codici di errore restituiti in \var{errno} sono i seguenti:
+ \begin{errlist}
+ \item[\errcode{EBADF}] l'argomento \param{sockfd} non è un file descriptor
+ valido.
+ \item[\errcode{ENOTSOCK}] l'argomento \param{sockfd} non è un socket.
+ \item[\errcode{ENOTCONN}] il socket non è connesso.
+ \item[\errcode{ENOBUFS}] non ci sono risorse sufficienti nel sistema per
+ eseguire l'operazione.
+ \item[\errcode{EFAULT}] l'argomento \param{name} punta al di fuori dello
+ spazio di indirizzi del processo.
+ \end{errlist}}
+\end{prototype}
+
+La funzione è identica a \func{getsockname}, ed usa la stessa sintassi, ma
+restituisce l'indirizzo remoto del socket, cioè quello associato all'altro
+capo della connessione. Ci si può chiedere a cosa serva questa funzione dato
+che dal lato client l'indirizzo remoto è sempre noto quando si esegue la
+\func{connect} mentre dal lato server si possono usare, come vedremo in
+\figref{fig:TCP_daytime_cunc_server_code}, i valori di ritorno di
+\func{accept}.
+
+Il fatto è che in generale quest'ultimo caso non è sempre possibile. In
+particolare questo avviene quando il server, invece di gestire la connessione
+direttamente in un processo figlio, come vedremo nell'esempio di server
+concorrente di \secref{sec:TCP_daytime_cunc_server}, lancia per ciascuna
+connessione un altro programma, usando \func{exec}.\footnote{questa ad esempio
+ è la modalità con cui opera il \textsl{super-server} \cmd{inetd}, che può
+ gestire tutta una serie di servizi diversi, eseguendo su ogni connessione
+ ricevuta sulle porte tenute sotto controllo, il relativo server.}
+
+In questo caso benché il processo figlio abbia una immagine della memoria che
+è copia di quella del processo padre (e contiene quindi anche la struttura
+ritornata da \func{accept}), all'esecuzione di \func{exec} verrà caricata in
+memoria l'immagine del programma eseguito, che a questo punto perde ogni
+riferimento ai valori tornati da \func{accept}. Il socket descriptor però
+resta aperto, e se si è seguita una opportuna convenzione per rendere noto al
+programma eseguito qual'è il socket connesso, \footnote{ad esempio il solito
+ \cmd{inetd} fa sempre in modo che i file descriptor 0, 1 e 2 corrispondano
+ al socket connesso.} quest'ultimo potrà usare la funzione \func{getpeername}
+per determinare l'indirizzo remoto del client.
+
+Infine è da chiarire (si legga la pagina di manuale) che, come per
+\func{accept}, il terzo parametro, che è specificato dallo standard POSIX.1g
+come di tipo \code{socklen\_t *} in realtà deve sempre corrispondere ad un
+\ctyp{int *} come prima dello standard perché tutte le implementazioni dei
+socket BSD fanno questa assunzione.
+
+
+\subsection{La funzione \func{close}}
+\label{sec:TCP_func_close}
+
+La funzione standard Unix \func{close} (vedi \secref{sec:file_close}) che si
+usa sui file può essere usata con lo stesso effetto anche sui file descriptor
+associati ad un socket.
+
+L'azione di questa funzione quando applicata a socket è di marcarlo come
+chiuso e ritornare immediatamente al processo. Una volta chiamata il socket
+descriptor non è più utilizzabile dal processo e non può essere usato come
+argomento per una \func{write} o una \func{read} (anche se l'altro capo della
+connessione non avesse chiuso la sua parte). Il kernel invierà comunque tutti
+i dati che ha in coda prima di iniziare la sequenza di chiusura.
+
+Vedremo più avanti in \secref{sec:TCP_so_linger} come è possibile cambiare
+questo comportamento, e cosa deve essere fatto perché il processo possa
+assicurarsi che l'altro capo abbia ricevuto tutti i dati.
+
+Come per tutti i file descriptor anche per i socket viene mantenuto un numero
+di riferimenti, per cui se più di un processo ha lo stesso socket aperto
+l'emissione del FIN e la sequenza di chiusura di TCP non viene innescata
+fintanto che il numero di riferimenti non si annulla, questo si applica, come
+visto in \secref{sec:file_sharing}, sia ai file descriptor duplicati che a
+quelli ereditati dagli eventuali processi figli, ed è il comportamento che ci
+si aspetta in una qualunque applicazione client/server.
+
+Per attivare immediatamente l'emissione del FIN e la sequenza di chiusura
+descritta in \secref{sec:TCP_conn_term}, si può invece usare la funzione
+\func{shutdown} su cui torneremo in seguito (vedi \secref{sec:xxx_shutdown}).
+
+
+
+\section{Un esempio elementare: il servizio \textit{daytime}}
+\label{sec:TCP_daytime_application}
+
+Avendo introdotto le funzioni di base per la gestione dei socket, potremo
+vedere in questa sezione un primo esempio di applicazione elementare che
+implementa il servizio \textit{daytime} su TCP, secondo quanto specificato
+dall'\href{http://www.ietf.org/rfc/rfc0867.txt}{RFC~867}. Prima di passare
+agli esempi del client e del server, inizieremo riesaminando con maggiori
+dettagli una peculiarità delle funzioni di I/O, già accennata in
+\secref{sec:file_read} e \secref{sec:file_write}, che nel caso dei socket è
+particolarmente rilevante. Passeremo poi ad illustrare gli esempi
+dell'implementazione, sia dal lato client, che dal lato server, che si è
+realizzato sia in forma iterativa che concorrente.
+
+
+\subsection{Il comportamento delle funzioni di I/O}
+\label{sec:sock_io_behav}
+
+Una cosa che si tende a dimenticare quando si ha a che fare con i socket è che
+le funzioni di input/output non sempre hanno lo stesso comportamento che
+avrebbero con i normali file di dati (in particolare questo accade per i
+socket di tipo stream).
+
+Infatti con i socket è comune che funzioni come \func{read} o \func{write}
+possano restituire in input o scrivere in output un numero di byte minore di
+quello richiesto. Come già accennato in \secref{sec:file_read} questo è un
+comportamento normale per le funzioni di I/O, ma con i normali file di dati il
+problema si avverte solo in lettura, quando si incontra la fine del file. In
+generale non è così, e con i socket questo è particolarmente evidente.
+
+
+\begin{figure}[htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/FullRead.c}
+ \end{minipage}
+ \normalsize
+ \caption{La funzione \func{FullRead}, che legge esattamente \var{count} byte
+ da un file descriptor, iterando opportunamente le letture.}
+ \label{fig:sock_FullRead_code}
+\end{figure}
+
+Quando ci si trova ad affrontare questo comportamento tutto quello che si deve
+fare è semplicemente ripetere la lettura (o la scrittura) per la quantità di
+byte restanti, tenendo conto che le funzioni si possono bloccare se i dati non
+sono disponibili: è lo stesso comportamento che si può avere scrivendo più di
+\const{PIPE\_BUF} byte in una pipe (si riveda quanto detto in
+\secref{sec:ipc_pipes}).
+
+Per questo motivo, seguendo l'esempio di R. W. Stevens in \cite{UNP1}, si sono
+definite due funzioni, \func{FullRead} e \func{FullWrite}, che eseguono
+lettura e scrittura tenendo conto di questa caratteristica, ed in grado di
+ritornare solo dopo avere letto o scritto esattamente il numero di byte
+specificato; il sorgente è riportato rispettivamente in
+\figref{fig:sock_FullRead_code} e \figref{fig:sock_FullWrite_code} ed è
+disponibile fra i sorgenti allegati alla guida nei file \file{FullRead.c} e
+\file{FullWrite.c}.
+
+\begin{figure}[htb]
+ \centering
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/FullWrite.c}
+ \end{minipage}
+ \normalsize
+ \caption{La funzione \func{FullWrite}, che scrive esattamente \var{count}
+ byte su un file descriptor, iterando opportunamente le scritture.}
+ \label{fig:sock_FullWrite_code}
+\end{figure}
+
+Come si può notare le due funzioni ripetono la lettura/scrittura in un ciclo
+fino all'esaurimento del numero di byte richiesti, in caso di errore viene
+controllato se questo è \errcode{EINTR} (cioè un'interruzione della system
+call dovuta ad un segnale), nel qual caso l'accesso viene ripetuto, altrimenti
+l'errore viene ritornato al programma chiamante, interrompendo il ciclo.
+
+Nel caso della lettura, se il numero di byte letti è zero, significa che si è
+arrivati alla fine del file (per i socket questo significa in genere che
+l'altro capo è stato chiuso, e quindi non sarà più possibile leggere niente) e
+pertanto si ritorna senza aver concluso la lettura di tutti i byte
+richiesti. Entrambe le funzioni restituiscono 0 in caso di successo, ed un
+valore negativo in caso di errore, \texttt{FullRead} restituisce il numero di
+byte non letti in caso di end-of-file prematuro.
+
+
+\subsection{Il client \textit{daytime}}
+\label{sec:TCP_daytime_client}
+
+Il primo esempio di applicazione delle funzioni di base illustrate in
+\secref{sec:TCP_functions} è relativo alla creazione di un client elementare
+per il servizio \textit{daytime}, un servizio elementare, definito
+nell'\href{http://www.ietf.org/rfc/rfc0867.txt}{RFC~867}, che restituisce
+l'ora locale della macchina a cui si effettua la richiesta, e che è assegnato
+alla porta 13.
+
+In \figref{fig:TCP_daytime_client_code} è riportata la sezione principale del
+codice del nostro client. Il sorgente completo del programma
+(\file{TCP\_daytime.c}, che comprende il trattamento delle opzioni ed una
+funzione per stampare un messaggio di aiuto) è allegato alla guida nella
+sezione dei codici sorgente e può essere compilato su una qualunque macchina
+GNU/Linux.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/TCP_daytime.c}
+ \end{minipage}
+ \normalsize
+ \caption{Esempio di codice di un client elementare per il servizio
+ \textit{daytime}.}
+ \label{fig:TCP_daytime_client_code}
+\end{figure}
+
+Il programma anzitutto (\texttt{\small 1--5}) include gli header necessari;
+dopo la dichiarazione delle variabili (\texttt{\small 9--12}) si è omessa
+tutta la parte relativa al trattamento degli argomenti passati dalla linea di
+comando (effettuata con le apposite funzioni illustrate in
+\secref{sec:proc_opt_handling}).
+
+Il primo passo (\texttt{\small 14--18}) è creare un socket TCP (quindi di tipo
+\const{SOCK\_STREAM} e di famiglia \const{AF\_INET}). La funzione
+\func{socket} ritorna il descrittore che viene usato per identificare il
+socket in tutte le chiamate successive. Nel caso la chiamata fallisca si
+stampa un errore (\texttt{\small 16}) con la funzione \func{perror} e si esce
+(\texttt{\small 17}) con un codice di errore.
+
+Il passo seguente (\texttt{\small 19--27}) è quello di costruire un'apposita
+struttura \struct{sockaddr\_in} in cui sarà inserito l'indirizzo del server ed
+il numero della porta del servizio. Il primo passo (\texttt{\small 20}) è
+inizializzare tutto a zero, per poi inserire il tipo di indirizzo
+(\texttt{\small 21}) e la porta (\texttt{\small 22}), usando per quest'ultima
+la funzione \func{htons} per convertire il formato dell'intero usato dal
+computer a quello usato nella rete, infine \texttt{\small 23--27} si può
+utilizzare la funzione \func{inet\_pton} per convertire l'indirizzo numerico
+passato dalla linea di comando.
+
+A questo punto (\texttt{\small 28--32}) usando la funzione \func{connect} sul
+socket creato in precedenza (\texttt{\small 29}) si può stabilire la
+connessione con il server. Per questo si deve utilizzare come secondo
+argomento la struttura preparata in precedenza con il relativo indirizzo; si
+noti come, esistendo diversi tipi di socket, si sia dovuto effettuare un cast.
+Un valore di ritorno della funzione negativo implica il fallimento della
+connessione, nel qual caso si stampa un errore (\texttt{\small 30}) e si
+ritorna (\texttt{\small 31}).
+
+Completata con successo la connessione il passo successivo (\texttt{\small
+ 34--40}) è leggere la data dal socket; il protocollo prevede che il server
+invii sempre una stringa alfanumerica, il formato della stringa non è
+specificato dallo standard, per cui noi useremo il formato usato dalla
+funzione \func{ctime}, seguito dai caratteri di terminazione \verb|\r\n|, cioè
+qualcosa del tipo:
+\begin{verbatim}
+Wed Apr 4 00:53:00 2001\r\n
+\end{verbatim}
+questa viene letta dal socket (\texttt{\small 34}) con la funzione \func{read}
+in un buffer temporaneo; la stringa poi deve essere terminata (\texttt{\small
+ 35}) con il solito carattere nullo per poter essere stampata (\texttt{\small
+ 36}) sullo standard output con l'uso di \func{fputs}.
+
+Come si è già spiegato in \secref{sec:sock_io_behav} la risposta dal socket
+potrà arrivare in un unico pacchetto di 26 byte (come avverrà senz'altro nel
+caso in questione) ma potrebbe anche arrivare in 26 pacchetti di un byte. Per
+questo nel caso generale non si può mai assumere che tutti i dati arrivino con
+una singola lettura, pertanto quest'ultima deve essere effettuata in un ciclo
+in cui si continui a leggere fintanto che la funzione \func{read} non ritorni
+uno zero (che significa che l'altro capo ha chiuso la connessione) o un numero
+minore di zero (che significa un errore nella connessione).
+
+Si noti come in questo caso la fine dei dati sia specificata dal server che
+chiude la connessione (anche questo è quanto richiesto dal protocollo); questa
+è una delle tecniche possibili (è quella usata pure dal protocollo HTTP), ma
+ce ne possono essere altre, ad esempio FTP marca la conclusione di un blocco
+di dati con la sequenza ASCII \verb|\r\n| (carriage return e line feed),
+mentre il DNS mette la lunghezza in testa ad ogni blocco che trasmette. Il
+punto essenziale è che TCP non provvede nessuna indicazione che permetta di
+marcare dei blocchi di dati, per cui se questo è necessario deve provvedere il
+programma stesso.
+
+Se abilitiamo il servizio \textit{daytime}\footnote{in genere questo viene
+ fornito direttamente dal \textsl{superdemone} \texttt{inetd}, pertanto basta
+ assicurarsi che esso sia abilitato nel relativo file di configurazione.}
+possiamo verificare il funzionamento del nostro client, avremo allora:
+\begin{verbatim}
+[piccardi@gont sources]$ ./daytime 127.0.0.1
+Mon Apr 21 20:46:11 2003
+\end{verbatim}%$
+e come si vede tutto funziona regolarmente.
+
+
+\subsection{Un server \textit{daytime} iterativo}
+\label{sec:TCP_daytime_iter_server}
+
+Dopo aver illustrato il client daremo anche un esempio di un server
+elementare, che sia anche in grado di rispondere al precedente client. Come
+primo esempio realizzeremo un server iterativo, in grado di fornire una sola
+risposta alla volta. Il codice del programma è nuovamente mostrato in
+\figref{fig:TCP_daytime_iter_server_code}, il sorgente completo
+(\file{TCP\_iter\_daytimed.c}) è allegato insieme agli altri file degli esempi.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/TCP_iter_daytimed.c}
+ \end{minipage}
+ \normalsize
+ \caption{Esempio di codice di un semplice server per il servizio daytime.}
+ \label{fig:TCP_daytime_iter_server_code}
+\end{figure}
+
+Come per il client si includono (\texttt{\small 1--9}) gli header necessari a
+cui è aggiunto quello per trattare i tempi, e si definiscono (\texttt{\small
+ 14--18}) alcune costanti e le variabili necessarie in seguito. Come nel caso
+precedente si sono omesse le parti relative al trattamento delle opzioni da
+riga di comando.
+
+La creazione del socket (\texttt{\small 20--24}) è analoga al caso precedente,
+come pure l'inizializzazione (\texttt{\small 25--29}) della struttura
+\struct{sockaddr\_in}. Anche in questo caso (\texttt{\small 28}) si usa la
+porta standard del servizio daytime, ma come indirizzo IP si usa
+(\texttt{\small 27}) il valore predefinito \const{INET\_ANY}, che corrisponde
+all'indirizzo generico.
+
+Si effettua poi (\texttt{\small 30--34}) la chiamata alla funzione \func{bind}
+che permette di associare la precedente struttura al socket, in modo che
+quest'ultimo possa essere usato per accettare connessioni su una qualunque
+delle interfacce di rete locali. In caso di errore si stampa (\texttt{\small
+ 31}) un messaggio, e si termina (\texttt{\small 32}) immediatamente il
+programma.
+
+Il passo successivo (\texttt{\small 35--39}) è quello di mettere ``in
+ascolto'' il socket; questo viene fatto (\texttt{\small 36}) con la funzione
+\func{listen} che dice al kernel di accettare connessioni per il socket che
+abbiamo creato; la funzione indica inoltre, con il secondo parametro, il
+numero massimo di connessioni che il kernel accetterà di mettere in coda per
+il suddetto socket. Di nuovo in caso di errore si stampa (\texttt{\small 37})
+un messaggio, e si esce (\texttt{\small 38}) immediatamente.
+
+La chiamata a \func{listen} completa la preparazione del socket per l'ascolto
+(che viene chiamato anche \textit{listening descriptor}) a questo punto si può
+procedere con il ciclo principale (\texttt{\small 40--53}) che viene eseguito
+indefinitamente. Il primo passo (\texttt{\small 42}) è porsi in attesa di
+connessioni con la chiamata alla funzione \func{accept}, come in precedenza in
+caso di errore si stampa (\texttt{\small 43}) un messaggio, e si esce
+(\texttt{\small 44}).
+
+Il processo resterà in stato di \textit{sleep} fin quando non arriva e viene
+accettata una connessione da un client; quando questo avviene \func{accept}
+ritorna, restituendo un secondo descrittore, che viene chiamato
+\textit{connected descriptor}, e che è quello che verrà usato dalla successiva
+chiamata alla \func{write} per scrivere la risposta al client.
+
+Il ciclo quindi proseguirà determinando (\texttt{\small 46}) il tempo corrente
+con una chiamata a \texttt{time}, con il quale si potrà opportunamente
+costruire (\texttt{\small 47}) la stringa con la data da trasmettere
+(\texttt{\small 48}) con la chiamata a \func{write}. Completata la
+trasmissione il nuovo socket viene chiuso (\texttt{\small 52}). A questo
+punto il ciclo si chiude ricominciando da capo in modo da poter ripetere
+l'invio della data in risposta ad una successiva connessione.
+
+È importante notare che questo server è estremamente elementare, infatti, a
+parte il fatto di poter essere usato solo con indirizzi IPv4, esso è in grado
+di rispondere ad un solo un client alla volta: è cioè, come dicevamo, un
+\textsl{server iterativo}. Inoltre è scritto per essere lanciato da linea di
+comando, se lo si volesse utilizzare come demone occorrerebbero le opportune
+modifiche\footnote{come una chiamata a \func{daemon} prima dell'inizio del
+ ciclo principale.} per tener conto di quanto illustrato in
+\secref{sec:sess_daemon}. Si noti anche che non si è inserita nessuna forma di
+gestione della terminazione del processo, dato che tutti i file descriptor
+vengono chiusi automaticamente alla sua uscita, e che, non generando figli,
+non è necessario preoccuparsi di gestire la loro terminazione.
+
+
+\subsection{Un server \textit{daytime} concorrente}
+\label{sec:TCP_daytime_cunc_server}
+
+Il server \texttt{daytime} dell'esempio in
+\secref{sec:TCP_daytime_iter_server} è un tipico esempio di server iterativo,
+in cui viene servita una richiesta alla volta; in generale però, specie se il
+servizio è più complesso e comporta uno scambio di dati più sostanzioso di
+quello in questione, non è opportuno bloccare un server nel servizio di un
+client per volta; per questo si ricorre alle capacità di multitasking del
+sistema.
+
+Come accennato anche in \secref{sec:proc_gen} una delle modalità più comuni di
+funzionamento da parte dei server è quella di usare la funzione \func{fork}
+per creare, ad ogni richiesta da parte di un client, un processo figlio che si
+incarichi della gestione della comunicazione. Si è allora riscritto il server
+\textit{daytime} dell'esempio precedente in forma concorrente, inserendo anche
+una opzione per la stampa degli indirizzi delle connessioni ricevute.
+
+In \figref{fig:TCP_daytime_cunc_server_code} è mostrato un estratto del
+codice, in cui si sono tralasciati il trattamento delle opzioni e le parti
+rimaste invariate rispetto al precedente esempio (cioè tutta la parte
+riguardante l'apertura passiva del socket). Al solito il sorgente completo del
+server, nel file \file{TCP\_cunc\_daytimed.c}, è allegato insieme ai sorgenti
+degli altri esempi.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/TCP_cunc_daytimed.c}
+ \end{minipage}
+ \normalsize
+ \caption{Esempio di codice di un server concorrente elementare per il
+ servizio daytime.}
+ \label{fig:TCP_daytime_cunc_server_code}
+\end{figure}
+
+Stavolta (\texttt{\small 21--25}) la funzione \func{accept} è chiamata
+fornendo una struttura di indirizzi in cui saranno ritornati l'indirizzo IP e
+la porta da cui il client effettua la connessione, che in un secondo tempo,
+(\texttt{\small 39--43}), se il logging è abilitato, stamperemo sullo standard
+output.
+
+Quando \func{accept} ritorna il server chiama la funzione \func{fork}
+(\texttt{\small 26--30}) per creare il processo figlio che effettuerà
+(\texttt{\small 31--45}) tutte le operazioni relative a quella connessione,
+mentre il padre proseguirà l'esecuzione del ciclo principale in attesa di
+ulteriori connessioni.
+
+Si noti come il figlio operi solo sul socket connesso, chiudendo
+immediatamente (\texttt{\small 32}) il socket \var{list\_fd}; mentre il padre
+continua ad operare (\texttt{\small 47}) solo sul socket in ascolto chiudendo
+\var{sock\_fd} al ritorno dalla \func{fork}. Per quanto abbiamo detto in
+\secref{sec:TCP_func_close} nessuna delle due chiamate a \func{close} causa
+l'innesco della sequenza di chiusura perché il numero di riferimenti al file
+descriptor non si è annullato.
+
+Infatti subito dopo la creazione del socket \var{list\_fd} ha una referenza, e
+lo stesso vale per \var{sock\_fd} dopo il ritorno di \func{accept}, ma dopo la
+\func{fork} i descrittori vengono duplicati nel padre e nel figlio per cui
+entrambi i socket si trovano con due referenze. Questo fa si che quando il
+padre chiude \var{sock\_fd} esso resta con una referenza da parte del figlio,
+e sarà definitivamente chiuso solo quando quest'ultimo, dopo aver completato
+le sue operazioni, chiamerà (\texttt{\small 44}) la funzione \func{close}.
+
+In realtà per il figlio non sarebbe necessaria nessuna chiamata a
+\func{close}, in quanto con la \func{exit} finale (\texttt{\small 45}) tutti i
+file descriptor, quindi anche quelli associati ai socket, vengono
+automaticamente chiusi. Tuttavia si è preferito effettuare esplicitamente le
+chiusure per avere una maggiore chiarezza del codice, e per evitare eventuali
+errori, prevenendo ad esempio un uso involontario del \textit{listening
+ descriptor}.
+
+Si noti invece come sia essenziale che il padre chiuda ogni volta il socket
+connesso dopo la \func{fork}; se così non fosse nessuno di questi socket
+sarebbe effettivamente chiuso dato che alla chiusura da parte del figlio
+resterebbe ancora un riferimento nel padre. Si avrebbero così due effetti: il
+padre potrebbe esaurire i descrittori disponibili (che sono un numero limitato
+per ogni processo) e soprattutto nessuna delle connessioni con i client
+verrebbe chiusa.
+
+Come per ogni server iterativo il lavoro di risposta viene eseguito
+interamente dal processo figlio. Questo si incarica (\texttt{\small 33}) di
+chiamare \func{time} per leggere il tempo corrente, e di stamparlo
+(\texttt{\small 34}) sulla stringa contenuta in \var{buffer} con l'uso di
+\func{snprintf} e \func{ctime}. Poi la stringa viene scritta (\texttt{\small
+ 35--38}) sul socket, controllando che non ci siano errori. Anche in questo
+caso si è evitato il ricorso a \func{FullWrite} in quanto la stringa è
+estremamente breve e verrà senz'altro scritta in un singolo segmento.
+
+Inoltre nel caso sia stato abilitato il \textit{logging} delle connessioni, si
+provvede anche (\texttt{\small 39--42}) a stampare sullo standard output
+l'indirizzo e la porta da cui il client ha effettuato la connessione, usando
+i valori contenuti nelle strutture restituite da \func{accept}, eseguendo le
+opportune conversioni con \func{inet\_ntop} e \func{atohs}.
+
+Ancora una volta l'esempio è estremamente semplificato, si noti come di nuovo
+non si sia gestita né la terminazione del processo né il suo uso come demone,
+che tra l'altro sarebbe stato incompatibile con l'uso della opzione di logging
+che stampa gli indirizzi delle connessioni sullo standard output. Un altro
+aspetto tralasciato è la gestione della terminazione dei processi figli,
+torneremo su questo più avanti quando tratteremo alcuni esempi di server più
+complessi.
+
+
+
+\section{Un esempio più completo: il servizio \textit{echo}}
+\label{sec:TCP_echo_application}
+
+L'esempio precedente, basato sul servizio \textit{daytime}, è un esempio molto
+elementare, in cui il flusso dei dati va solo nella direzione dal server al
+client. In questa sezione esamineremo un esempio di applicazione client/server
+un po' più complessa, che usi i socket TCP per una comunicazione in entrambe
+le direzioni.
+
+Ci limiteremo a fornire una implementazione elementare, che usi solo le
+funzioni di base viste finora, ma prenderemo in esame, oltre al comportamento
+in condizioni normali, anche tutti i possibili scenari particolari (errori,
+sconnessione della rete, crash del client o del server durante la connessione)
+che possono avere luogo durante l'impiego di un'applicazione di rete, partendo
+da una versione primitiva che dovrà essere rimaneggiata di volta in volta per
+poter tenere conto di tutte le evenienze che si possono manifestare nella vita
+reale di un'applicazione di rete, fino ad arrivare ad un'implementazione
+completa.
+
+
+\subsection{Il servizio \textit{echo}}
+\label{sec:TCP_echo}
+
+
+Nella ricerca di un servizio che potesse fare da esempio per una comunicazione
+bidirezionale, si è deciso, seguendo la scelta di Stevens in \cite{UNP1}, di
+usare il servizio \textit{echo}, che si limita a restituire in uscita quanto
+immesso in ingresso. Infatti, nonostante la sua estrema semplicità, questo
+servizio costituisce il prototipo ideale per una generica applicazione di rete
+in cui un server risponde alle richieste di un client. Nel caso di una
+applicazione più complessa quello che si potrà avere in più è una elaborazione
+dell'input del client, che in molti casi viene interpretato come un comando,
+da parte di un server che risponde fornendo altri dati in uscita.
+
+Il servizio \textit{echo} è uno dei servizi standard solitamente provvisti
+direttamente dal superserver \cmd{inetd}, ed è definito
+dall'\href{http://www.ietf.org/rfc/rfc0862.txt}{RFC~862}. Come dice il nome il
+servizio deve riscrivere indietro sul socket i dati che gli vengono inviati in
+ingresso. L'RFC descrive le specifiche del servizio sia per TCP che UDP, e per
+il primo stabilisce che una volta stabilita la connessione ogni dato in
+ingresso deve essere rimandato in uscita fintanto che il chiamante non ha
+chiude la connessione. Al servizio è assegnata la porta riservata 7.
+
+Nel nostro caso l'esempio sarà costituito da un client che legge una linea di
+caratteri dallo standard input e la scrive sul server. A sua volta il server
+leggerà la linea dalla connessione e la riscriverà immutata all'indietro. Sarà
+compito del client leggere la risposta del server e stamparla sullo standard
+output.
+
+
+\subsection{Il client: prima versione}
+\label{sec:TCP_echo_client}
+
+Il codice della prima versione del client per il servizio \textit{echo},
+disponibile nel file \file{TCP\_echo\_first.c}, è riportato in
+\figref{fig:TCP_echo_client_1}. Esso ricalca la struttura del precedente
+client per il servizio \textit{daytime} (vedi
+\secref{sec:TCP_daytime_client}), e la prima parte (\texttt{\small 10--27}) è
+sostanzialmente identica, a parte l'uso di una porta diversa.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6 cm}
+ \includecodesample{listati/TCP_echo_first.c}
+ \end{minipage}
+ \normalsize
+ \caption{Codice della prima versione del client \textit{echo}.}
+ \label{fig:TCP_echo_client_1}
+\end{figure}
+
+Al solito si è tralasciata la sezione relativa alla gestione delle opzioni a
+riga di comando. Una volta dichiarate le variabili, si prosegue
+(\texttt{\small 10--13}) con della creazione del socket con l'usuale controllo
+degli errori, alla preparazione (\texttt{\small 14--17}) della struttura
+dell'indirizzo, che stavolta usa la porta 7 riservata al servizio
+\textit{echo}, infine si converte (\texttt{\small 18--22}) l'indirizzo
+specificato a riga di comando. A questo punto (\texttt{\small 23--27}) si può
+eseguire la connessione al server secondo la stessa modalità usata in
+\secref{sec:TCP_daytime_client}.
+
+Completata la connessione, per gestire il funzionamento del protocollo si usa
+la funzione \code{ClientEcho}, il cui codice si è riportato a parte in
+\figref{fig:TCP_client_echo_sub}. Questa si preoccupa di gestire tutta la
+comunicazione, leggendo una riga alla volta dallo standard input \file{stdin},
+scrivendola sul socket e ristampando su \file{stdout} quanto ricevuto in
+risposta dal server. Al ritorno dalla funzione (\texttt{\small 30--31}) anche
+il programma termina.
+
+La funzione \code{ClientEcho} utilizza due buffer (\texttt{\small 3}) per
+gestire i dati inviati e letti sul socket. La comunicazione viene gestita
+all'interno di un ciclo (\texttt{\small 5--10}), i dati da inviare sulla
+connessione vengono presi dallo \file{stdin} usando la funzione \func{fgets},
+che legge una linea di testo (terminata da un \texttt{CR} e fino al massimo di
+\const{MAXLINE} caratteri) e la salva sul buffer di invio.
+
+Si usa poi (\texttt{\small 6}) la funzione \func{FullWrite}, vista in
+\secref{sec:sock_io_behav}, per scrivere i dati sul socket, gestendo
+automaticamente l'invio multiplo qualora una singola \func{write} non sia
+sufficiente. I dati vengono riletti indietro (\texttt{\small 7}) con una
+\func{read}\footnote{si è fatta l'assunzione implicita che i dati siano
+ contenuti tutti in un solo segmento, così che la chiamata a \texttt{read} li
+ restituisca sempre tutti; avendo scelto una dimensione ridotta per il buffer
+ questo sarà sempre vero, vedremo più avanti come superare il problema di
+ rileggere indietro tutti e soli i dati disponibili, senza bloccarsi.} sul
+buffer di ricezione e viene inserita (\texttt{\small 8}) la terminazione della
+stringa e per poter usare (\texttt{\small 9}) la funzione \func{fputs} per
+scriverli su \file{stdout}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/ClientEcho.c}
+ \end{minipage}
+ \normalsize
+ \caption{Codice della prima versione della funzione \texttt{ClientEcho} per
+ la gestione del servizio \textit{echo}.}
+ \label{fig:TCP_client_echo_sub}
+\end{figure}
+
+Quando si concluderà l'invio di dati mandando un end-of-file sullo standard
+input si avrà il ritorno di \func{fgets} con un puntatore nullo (si riveda
+quanto spiegato in \secref{sec:file_line_io}) e la conseguente uscita dal
+ciclo; al che la subroutine ritorna ed il nostro programma client termina.
+
+Si può effettuare una verifica del funzionamento del client abilitando il
+servizio \textit{echo} nella configurazione di \cmd{initd} sulla propria
+macchina ed usandolo direttamente verso di esso in locale, vedremo in
+dettaglio più avanti (in \secref{sec:TCP_echo_startup}) il funzionamento del
+programma, usato però con la nostra versione del server \textit{echo}, che
+illustriamo immediatamente.
+
+
+\subsection{Il server: prima versione}
+\label{sec:TCPsimp_server_main}
+
+La prima versione del server, contenuta nel file \file{TCP\_echod\_first.c}, è
+riportata in \figref{fig:TCP_echo_server_first_code}. Come abbiamo fatto per
+il client anche il server è stato diviso in un corpo principale, costituito
+dalla funzione \code{main}, che è molto simile a quello visto nel precedente
+esempio per il server del servizio \textit{daytime} di
+\secref{sec:TCP_daytime_cunc_server}, e da una funzione ausiliaria
+\code{ServEcho} che si cura della gestione del servizio.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/TCP_echod_first.c}
+ \end{minipage}
+ \normalsize
+ \caption{Codice del corpo principale della prima versione del server
+ per il servizio \textit{echo}.}
+ \label{fig:TCP_echo_server_first_code}
+\end{figure}
+
+In questo caso però, rispetto a quanto visto nell'esempio di
+\figref{fig:TCP_daytime_cunc_server_code} si è preferito scrivere il server
+curando maggiormente alcuni dettagli, per tenere conto anche di alcune
+esigenze generali (che non riguardano direttamente la rete), come la
+possibilità di lanciare il server anche in modalità interattiva e la cessione
+dei privilegi di amministratore non appena questi non sono più necessari.
+
+La sezione iniziale del programma (\texttt{\small 8--21}) è la stessa del
+server di \secref{sec:TCP_daytime_cunc_server}, ed ivi descritta in dettaglio:
+crea il socket, inizializza l'indirizzo e esegue \func{bind}; dato che
+quest'ultima funzione viene usata su una porta riservata, il server dovrà
+essere eseguito da un processo con i privilegi di amministratore, pena il
+fallimento della chiamata.
+
+Una volta eseguita la funzione \func{bind} però i privilegi di amministratore
+non sono più necessari, per questo è sempre opportuno rilasciarli, in modo da
+evitare problemi in caso di eventuali vulnerabilità del server. Per questo
+prima (\texttt{\small 22--26}) si esegue \func{setgid} per assegnare il
+processo ad un gruppo senza privilegi,\footnote{si è usato il valore 65534,
+ ovvero -1 per il formato \ctyp{short}, che di norma in tutte le
+ distribuzioni viene usato per identificare il gruppo \texttt{nogroup} e
+ l'utente \texttt{nobody}, usati appunto per eseguire programmi che non
+ richiedono nessun privilegio particolare.} e poi si ripete (\texttt{\small
+ 27--30}) l'operazione usando \func{setuid} per cambiare anche
+l'utente.\footnote{si tenga presente che l'ordine in cui si eseguono queste
+ due operazioni è importante, infatti solo avendo i privilegi di
+ amministratore si può cambiare il gruppo di un processo ad un'altro di cui
+ non si fa parte, per cui chiamare prima \func{setuid} farebbe fallire una
+ successiva chiamata a \func{setgid}. Inoltre si ricordi (si riveda quanto
+ esposto in \secref{sec:proc_perms}) che usando queste due funzioni il
+ rilascio dei privilegi è irreversibile.} Infine (\texttt{\small 30--36}),
+qualora sia impostata la variabile \var{demonize}, prima (\texttt{\small 31})
+si apre il sistema di logging per la stampa degli errori, e poi
+(\texttt{\small 32--35}) si invoca \func{daemon} per eseguire in background il
+processo come demone.
+
+A questo punto il programma riprende di nuovo lo schema già visto usato dal
+server per il servizio \textit{daytime}, con l'unica differenza della chiamata
+alla funzione \code{PrintErr}, riportata in \figref{fig:TCP_PrintErr}, al
+posto di \func{perror} per la stampa degli errori.
+
+Si inizia con il porre (\texttt{\small 37--41}) in ascolto il socket, e poi si
+esegue indefinitamente il ciclo principale (\texttt{\small 42--58}).
+All'interno di questo si ricevono (\texttt{\small 43--46}) le connessioni,
+creando (\texttt{\small 47--50}) un processo figlio per ciascuna di esse.
+Quest'ultimo (\texttt{\small 51--55}), chiuso (\texttt{\small 52}) il
+\textit{listening socket}, esegue (\texttt{\small 53}) la funzione di gestione
+del servizio \code{ServEcho}, ed al ritorno di questa (\texttt{\small 54})
+esce.
+
+Il padre invece si limita (\texttt{\small 56}) a chiudere il \textit{connected
+ socket} per ricominciare da capo il ciclo in attesa di nuove connessioni. In
+questo modo si ha un server concorrente. La terminazione del padre non è
+gestita esplicitamente, e deve essere effettuata inviando un segnale al
+processo.
+
+Avendo trattato direttamente la gestione del programma come demone, si è
+dovuto anche provvedere alla necessità di poter stampare eventuali messaggi di
+errore attraverso il sistema del \textit{syslog} trattato in
+\secref{sec:sess_daemon}. Come accennato questo è stato fatto utilizzando come
+\textit{wrapper} la funzione \code{PrintErr}, il cui codice è riportato in
+\figref{fig:TCP_PrintErr}.
+
+In essa ci si limita a controllare (\texttt{\small 2}) se è stato impostato
+(valore attivo per default) l'uso come demone, nel qual caso (\texttt{\small
+ 3}) si usa \func{syslog} (vedi \secref{sec:sess_daemon}) per stampare il
+messaggio di errore fornito come argomento sui log di sistema. Se invece si è
+in modalità interattiva (attivabile con l'opzione \texttt{-i}) si usa
+(\texttt{\small 5}) semplicemente la funzione \func{perror} per stampare sullo
+standard error.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/PrintErr.c}
+ \end{minipage}
+ \normalsize
+ \caption{Codice della funzione \code{PrintErr} per la
+ generalizzazione della stampa degli errori sullo standard input o
+ attraverso il \texttt{syslog}.}
+ \label{fig:TCP_PrintErr}
+\end{figure}
+
+La gestione del servizio \textit{echo} viene effettuata interamente nella
+funzione \code{ServEcho}, il cui codice è mostrato in
+\figref{fig:TCP_ServEcho_first}, e la comunicazione viene gestita all'interno
+di un ciclo (\texttt{\small 6--13}). I dati inviati dal client vengono letti
+(\texttt{\small 6}) dal socket con una semplice \func{read}, di cui non si
+controlla lo stato di uscita, assumendo che ritorni solo in presenza di dati
+in arrivo. La riscrittura (\texttt{\small 7}) viene invece gestita dalla
+funzione \func{FullWrite} (descritta in \figref{fig:sock_FullWrite_code}) che
+si incarica di tenere conto automaticamente della possibilità che non tutti i
+dati di cui è richiesta la scrittura vengano trasmessi con una singola
+\func{write}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/ServEcho_first.c}
+ \end{minipage}
+ \normalsize
+ \caption{Codice della prima versione della funzione \code{ServEcho} per la
+ gestione del servizio \textit{echo}.}
+ \label{fig:TCP_ServEcho_first}
+\end{figure}
+
+In caso di errore di scrittura (si ricordi che \func{FullWrite} restituisce un
+valore nullo in caso di successo) si provvede (\texttt{\small 8--10}) a
+stampare il relativo messaggio con \func{PrintErr}. Quando il client chiude
+la connessione il ricevimento del FIN fa ritornare la \func{read} con un
+numero di byte letti pari a zero, il che causa l'uscita dal ciclo e il ritorno
+(\texttt{\small 12}) della funzione, che a sua volta causa la terminazione del
+processo figlio.
+
+
+\subsection{L'avvio e il funzionamento normale}
+\label{sec:TCP_echo_startup}
+
+Benché il codice dell'esempio precedente sia molto ridotto, esso ci permetterà
+di considerare in dettaglio le varie problematiche che si possono incontrare
+nello scrivere un'applicazione di rete. Infatti attraverso l'esame delle sue
+modalità di funzionamento normali, all'avvio e alla terminazione, e di quello
+che avviene nelle varie situazioni limite, da una parte potremo approfondire
+la comprensione del protocollo TCP/IP e dall'altra ricavare le indicazioni
+necessarie per essere in grado di scrivere applicazioni robuste, in grado di
+gestire anche i casi limite.
+
+Il primo passo è compilare e lanciare il server (da root, per poter usare la
+porta 7 che è riservata), alla partenza esso eseguirà l'apertura passiva con
+la sequenza delle chiamate a \func{socket}, \func{bind}, \func{listen} e poi
+si bloccherà nella \func{accept}. A questo punto si potrà controllarne lo
+stato con \cmd{netstat}:
+\begin{verbatim}
+[piccardi@roke piccardi]$ netstat -at
+Active Internet connections (servers and established)
+Proto Recv-Q Send-Q Local Address Foreign Address State
+...
+tcp 0 0 *:echo *:* LISTEN
+...
+\end{verbatim} %$
+che ci mostra come il socket sia in ascolto sulla porta richiesta, accettando
+connessioni da qualunque indirizzo e da qualunque porta e su qualunque
+interfaccia locale.
+
+A questo punto si può lanciare il client, esso chiamerà \func{socket} e
+\func{connect}; una volta completato il three way handshake la connessione è
+stabilita; la \func{connect} ritornerà nel client\footnote{si noti che è
+ sempre la \func{connect} del client a ritornare per prima, in quanto
+ questo avviene alla ricezione del secondo segmento (l'ACK del server) del
+ three way handshake, la \func{accept} del server ritorna solo dopo
+ un altro mezzo RTT quando il terzo segmento (l'ACK del client) viene
+ ricevuto.} e la \func{accept} nel server, ed usando di nuovo
+\cmd{netstat} otterremmo che:
+\begin{verbatim}
+Active Internet connections (servers and established)
+Proto Recv-Q Send-Q Local Address Foreign Address State
+tcp 0 0 *:echo *:* LISTEN
+tcp 0 0 roke:echo gont:32981 ESTABLISHED
+\end{verbatim}
+mentre per quanto riguarda l'esecuzione dei programmi avremo che:
+\begin{itemize}
+\item il client chiama la funzione \code{ClientEcho} che si blocca sulla
+ \func{fgets} dato che non si è ancora scritto nulla sul terminale.
+\item il server eseguirà una \func{fork} facendo chiamare al processo figlio
+ la funzione \code{ServEcho}, quest'ultima si bloccherà sulla \func{read}
+ dal socket sul quale ancora non sono presenti dati.
+\item il processo padre del server chiamerà di nuovo \func{accept}
+ bloccandosi fino all'arrivo di un'altra connessione.
+\end{itemize}
+e se usiamo il comando \cmd{ps} per esaminare lo stato dei processi otterremo
+un risultato del tipo:
+\begin{verbatim}
+[piccardi@roke piccardi]$ ps ax
+ PID TTY STAT TIME COMMAND
+ ... ... ... ... ...
+ 2356 pts/0 S 0:00 ./echod
+ 2358 pts/1 S 0:00 ./echo 127.0.0.1
+ 2359 pts/0 S 0:00 ./echod
+\end{verbatim} %$
+(dove si sono cancellate le righe inutili) da cui si evidenzia la presenza di
+tre processi, tutti in stato di \textit{sleep} (vedi
+\tabref{tab:proc_proc_states}).
+
+Se a questo punto si inizia a scrivere qualcosa sul client non sarà trasmesso
+niente fin tanto che non si prema il tasto di a capo (si ricordi quanto detto
+in \secref{sec:file_line_io} a proposito dell'I/O su terminale), solo allora
+\func{fgets} ritornerà ed il client scriverà quanto immesso sul socket, per
+poi passare a rileggere quanto gli viene inviato all'indietro dal server, che
+a sua volta sarà inviato sullo standard output, che nel caso ne provoca
+l'immediatamente stampa a video.
+
+
+\subsection{La conclusione normale}
+\label{sec:TCP_echo_conclusion}
+
+Tutto quello che scriveremo sul client sarà rimandato indietro dal server e
+ristampato a video fintanto che non concluderemo l'immissione dei dati; una
+sessione tipica sarà allora del tipo:
+\begin{verbatim}
+[piccardi@roke sources]$ ./echo 127.0.0.1
+Questa e` una prova
+Questa e` una prova
+Ho finito
+Ho finito
+\end{verbatim} %$
+che termineremo inviando un EOF dal terminale (usando la combinazione di tasti
+ctrl-D, che non compare a schermo); se eseguiamo un \cmd{netstat} a questo
+punto avremo:
+\begin{verbatim}
+[piccardi@roke piccardi]$ netstat -at
+tcp 0 0 *:echo *:* LISTEN
+tcp 0 0 localhost:33032 localhost:echo TIME_WAIT
+\end{verbatim} %$
+con il client che entra in \texttt{TIME\_WAIT}.
+
+Esaminiamo allora in dettaglio la sequenza di eventi che porta alla
+terminazione normale della connessione, che ci servirà poi da riferimento
+quando affronteremo il comportamento in caso di conclusioni anomale:
+
+\begin{enumerate}
+\item inviando un carattere di EOF da terminale la \func{fgets} ritorna
+ restituendo un puntatore nullo che causa l'uscita dal ciclo di \code{while},
+ così la funzione \code{ClientEcho} ritorna.
+\item al ritorno di \code{ClientEcho} ritorna anche la funzione \code{main}, e
+ come parte del processo terminazione tutti i file descriptor vengono chiusi
+ (si ricordi quanto detto in \secref{sec:proc_term_conclusion}); questo causa
+ la chiusura del socket di comunicazione; il client allora invierà un FIN al
+ server a cui questo risponderà con un ACK. A questo punto il client verrà a
+ trovarsi nello stato \texttt{FIN\_WAIT\_2} ed il server nello stato
+ \texttt{CLOSE\_WAIT} (si riveda quanto spiegato in
+ \secref{sec:TCP_conn_term}).
+\item quando il server riceve il FIN la \func{read} del processo figlio che
+ gestisce la connessione ritorna restituendo 0 causando così l'uscita dal
+ ciclo e il ritorno di \code{ServEcho}, a questo punto il processo figlio
+ termina chiamando \func{exit}.
+\item all'uscita del figlio tutti i file descriptor vengono chiusi, la
+ chiusura del socket connesso fa sì che venga effettuata la sequenza finale
+ di chiusura della connessione, viene emesso un FIN dal server che riceverà
+ un ACK dal client, a questo punto la connessione è conclusa e il client
+ resta nello stato \texttt{TIME\_WAIT}.
+\end{enumerate}
+
+
+\subsection{La gestione dei processi figli}
+\label{sec:TCP_child_hand}
+
+Tutto questo riguarda la connessione, c'è però da tenere conto dell'effetto
+del procedimento di chiusura del processo figlio nel server (si veda quanto
+esaminato in \secref{sec:proc_termination}). In questo caso avremo l'invio del
+segnale \const{SIGCHLD} al padre, ma dato che non si è installato un
+gestore e che l'azione predefinita per questo segnale è quella di essere
+ignorato, non avendo predisposto la ricezione dello stato di terminazione,
+otterremo che il processo figlio entrerà nello stato di zombie\index{zombie}
+(si riveda quanto illustrato in \secref{sec:sig_sigchld}), come risulterà
+ripetendo il comando \cmd{ps}:
+\begin{verbatim}
+ 2356 pts/0 S 0:00 ./echod
+ 2359 pts/0 Z 0:00 [echod <defunct>]
+\end{verbatim}
+
+Dato che non è il caso di lasciare processi zombie\index{zombie}, occorrerà
+ricevere opportunamente lo stato di terminazione del processo (si veda
+\secref{sec:proc_wait}), cosa che faremo utilizzando \const{SIGCHLD} secondo
+quanto illustrato in \secref{sec:sig_sigchld}. Una prima modifica al nostro
+server è pertanto quella di inserire la gestione della terminazione dei
+processi figli attraverso l'uso di un gestore. Per questo useremo la funzione
+\code{Signal} (che abbiamo illustrato in \figref{fig:sig_Signal_code}), per
+installare il gestore che riceve i segnali dei processi figli terminati già
+visto in \figref{fig:sig_sigchld_handl}. Basterà allora aggiungere il
+seguente codice: \includecodesnip{listati/sigchildhand.c}
+\noindent
+all'esempio illustrato in \figref{fig:TCP_echo_server_first_code}.
+
+In questo modo però si introduce un altro problema. Si ricordi infatti che,
+come spiegato in \secref{sec:sig_gen_beha}, quando un programma si trova in
+stato di \texttt{sleep} durante l'esecuzione di una system call, questa viene
+interrotta alla ricezione di un segnale. Per questo motivo, alla fine
+dell'esecuzione del gestore del segnale, se questo ritorna, il programma
+riprenderà l'esecuzione ritornando dalla system call interrotta con un errore
+di \errcode{EINTR}.
+
+Vediamo allora cosa comporta tutto questo nel nostro caso: quando si chiude il
+client, il processo figlio che gestisce la connessione terminerà, ed il padre,
+per evitare la creazione di zombie, riceverà il segnale \const{SIGCHLD}
+eseguendo il relativo gestore. Al ritorno del gestore però l'esecuzione nel
+padre ripartirà subito con il ritorno della funzione \func{accept} (a meno di
+un caso fortuito in cui il segnale arriva durante l'esecuzione del programma
+in risposta ad una connessione) con un errore di \errcode{EINTR}. Non avendo
+previsto questa eventualità il programma considera questo un errore fatale
+terminando a sua volta con un messaggio del tipo:
+\begin{verbatim}
+[root@gont sources]# ./echod -i
+accept error: Interrupted system call
+\end{verbatim}%#
+
+Come accennato in \secref{sec:sig_gen_beha} le conseguenze di questo
+comportamento delle system call possono essere superate in due modi diversi,
+il più semplice è quello di modificare il codice di \func{Signal} per
+richiedere il riavvio automatico delle system call interrotte secondo la
+semantica di BSD, usando l'opzione \const{SA\_RESTART} di \func{sigaction};
+rispetto a quanto visto in \figref{fig:sig_Signal_code}. Definiremo allora la
+nuova funzione \func{SignalRestart}\footnote{anche questa è definita, insieme
+ alle altre funzioni riguardanti la gestione dei segnali, nel file
+ \file{SigHand.c}, il cui contento completo può essere trovato negli esempi
+ allegati.} come mostrato in \figref{fig:sig_SignalRestart_code}, ed
+installeremo il gestore usando quest'ultima.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/SignalRestart.c}
+ \end{minipage}
+ \normalsize
+ \caption{La funzione \funcd{SignalRestart}, che installa un gestore di
+ segnali in semantica BSD per il riavvio automatico delle system call
+ interrotte.}
+ \label{fig:sig_SignalRestart_code}
+\end{figure}
+
+Come si può notare questa funzione è identica alla precedente \func{Signal},
+illustrata in \figref{fig:sig_Signal_code}, solo che in questo caso invece di
+inizializzare a zero il campo \var{sa\_flags} di \struct{sigaction}, lo si
+inizializza (\texttt{\small 5}) al valore \const{SA\_RESTART}. Usando questa
+funzione al posto di \func{Signal} nel server non è necessaria nessuna altra
+modifica: le system call interrotte saranno automaticamente riavviate, e
+l'errore \errcode{EINTR} non si manifesterà più.
+
+La seconda soluzione è più invasiva e richiede di controllare tutte le volte
+l'errore restituito dalle varie system call, ripetendo la chiamata qualora
+questo corrisponda ad \errcode{EINTR}. Questa soluzione ha però il pregio
+della portabilità, infatti lo standard POSIX dice che la funzionalità di
+riavvio automatico delle system call, fornita da \const{SA\_RESTART}, è
+opzionale, per cui non è detto che essa sia disponibile su qualunque sistema.
+Inoltre in certi casi,\footnote{Stevens in \cite{UNP1} accenna che la maggior
+ parte degli Unix derivati da BSD non fanno ripartire \func{select}; altri
+ non riavviano neanche \func{accept} e \func{recvfrom}, cosa che invece nel
+ caso di Linux viene sempre fatta.} anche quando questa è presente, non è
+detto possa essere usata con \func{accept}.
+
+
+La portabilità nella gestione dei segnali però viene al costo di una
+riscrittura parziale del server, la nuova versione di questo, in cui si sono
+introdotte una serie di nuove opzioni che ci saranno utili per il debug, è
+mostrata in \figref{fig:TCP_echo_server_code_second}, dove si sono riportate
+la sezioni di codice modificate nella seconda versione del programma, il
+sorgente completo di quest'ultimo si trova nel file
+\file{TCP\_echod\_second.c} dei sorgenti allegati alla guida.
+
+La prima modifica effettuata è stata quella di introdurre una nuova opzione a
+riga di comando, \texttt{-c}, che permette di richiedere il comportamento
+compatibile nella gestione di \const{SIGCHLD} al posto della semantica BSD
+impostando la variabile \var{compat} ad un valore non nullo. Questa è
+preimpostata al valore nullo, cosicché se non si usa questa opzione il
+comportamento di default del server è di usare la semantica BSD.
+
+Una seconda opzione aggiunta è quella di inserire un tempo di attesa fisso
+specificato in secondi fra il ritorno della funzione \func{listen} e la
+chiamata di \func{accept}, specificabile con l'opzione \texttt{-w}, che
+permette di impostare la variabile \var{waiting}. Infine si è introdotta una
+opzione \texttt{-d} per abilitare il debugging che imposta ad un valore non
+nullo la variabile \var{debugging}. Al solito si è omessa da
+\figref{fig:TCP_echo_server_code_second} la sezione di codice relativa alla
+gestione di tutte queste opzioni, che può essere trovata nel sorgente del
+programma.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/TCP_echod_second.c}
+ \end{minipage}
+ \normalsize
+ \caption{La sezione nel codice della seconda versione del server
+ per il servizio \textit{echo} modificata per tener conto dell'interruzione
+ delle system call.}
+ \label{fig:TCP_echo_server_code_second}
+\end{figure}
+
+Vediamo allora come è cambiato il nostro server; una volta definite le
+variabili e trattate le opzioni il primo passo (\texttt{\small 9--13}) è
+verificare la semantica scelta per la gestione di \const{SIGCHLD}, a seconda
+del valore di \var{compat} (\texttt{\small 9}) si installa il gestore con la
+funzione \func{Signal} (\texttt{\small 10}) o con \texttt{SignalRestart}
+(\texttt{\small 12}), essendo quest'ultimo il valore di default.
+
+Tutta la sezione seguente, che crea il socket, cede i privilegi di
+amministratore ed eventualmente lancia il programma come demone, è rimasta
+invariata e pertanto è stata omessa in
+\figref{fig:TCP_echo_server_code_second}; l'unica modifica effettuata prima
+dell'entrata nel ciclo principale è stata quella di aver introdotto, subito
+dopo la chiamata (\texttt{\small 17--20}) alla funzione \func{listen}, una
+eventuale pausa con una condizione (\texttt{\small 21}) sulla variabile
+\var{waiting}, che viene inizializzata, con l'opzione \code{-w Nsec}, al
+numero di secondi da aspettare (il valore preimpostato è nullo).
+
+Si è potuto lasciare inalterata tutta la sezione di creazione del socket
+perché nel server l'unica chiamata ad una system call critica, che può essere
+interrotta dall'arrivo di \const{SIGCHLD}, è quella ad \func{accept}, che è
+l'unica funzione che può mettere il processo padre in stato di sleep nel
+periodo in cui un figlio può terminare; si noti infatti come le altre
+\textit{slow system call}\footnote{si ricordi la distinzione fatta in
+ \secref{sec:sig_gen_beha}.} o sono chiamate prima di entrare nel ciclo
+principale, quando ancora non esistono processi figli, o sono chiamate dai
+figli stessi e non risentono di \const{SIGCHLD}.
+
+Per questo l'unica modifica sostanziale nel ciclo principale (\texttt{\small
+ 23--42}), rispetto precedente versione di \figref{fig:TCP_ServEcho_first}, è
+nella sezione (\texttt{\small 26--30}) in cui si effettua la chiamata di
+\func{accept}. Quest'ultima viene effettuata (\texttt{\small 26--27})
+all'interno di un ciclo di \code{while}\footnote{la sintassi del C relativa a
+ questo ciclo può non essere del tutto chiara. In questo caso infatti si è
+ usato un ciclo vuoto che non esegue nessuna istruzione, in questo modo
+ quello che viene ripetuto con il ciclo è soltanto il codice che esprime la
+ condizione all'interno del \code{while}.} che la ripete indefinitamente
+qualora in caso di errore il valore di \var{errno} sia \errcode{EINTR}. Negli
+altri casi si esce in caso di errore effettivo (\texttt{\small 27--29}),
+altrimenti il programma prosegue.
+
+Si noti che in questa nuova versione si è aggiunta una ulteriore sezione
+(\texttt{\small 31--39}) di aiuto per il debug del programma, che eseguita con
+un controllo (\texttt{\small 31}) sul valore della variabile \var{debugging}
+impostato dall'opzione \texttt{-d}. Qualora questo sia nullo, come
+preimpostato, non accade nulla. altrimenti (\texttt{\small 32}) l'indirizzo
+ricevuto da \var{accept} viene convertito in una stringa che poi
+(\texttt{\small 33--38}) viene opportunamente stampata o sullo schermo o nei
+log.
+
+
+
+
+\section{I vari scenari critici}
+\label{sec:TCP_echo_critical}
+
+Con le modifiche viste in \secref{sec:TCP_child_hand} il nostro esempio
+diventa in grado di affrontare la gestione ordinaria delle connessioni, ma un
+server di rete deve tenere conto che, al contrario di quanto avviene per i
+server che operano nei confronti di processi presenti sulla stessa macchina,
+la rete è di sua natura inaffidabile, per cui è necessario essere in grado di
+gestire tutta una serie di situazioni critiche che non esistono per i processi
+locali.
+
+
+\subsection{La terminazione precoce della connessione}
+\label{sec:TCP_conn_early_abort}
+
+La prima situazione critica è quella della terminazione precoce, causata da un
+qualche errore sulla rete, della connessione effettuata da un client. Come
+accennato in \secref{sec:TCP_func_accept} la funzione \func{accept} riporta
+tutti gli eventuali errori di rete pendenti su una connessione sul
+\textit{connected socket}. Di norma questo non è un problema, in quanto non
+appena completata la connessione, \func{accept} ritorna e l'errore sarà
+rilevato in seguito, dal processo che gestisce la connessione, alla prima
+chiamata di una funzione che opera sul socket.
+
+È però possibile, dal punto di vista teorico, incorrere anche in uno scenario
+del tipo di quello mostrato in \figref{fig:TCP_early_abort}, in cui la
+connessione viene abortita sul lato client per un qualche errore di rete con
+l'invio di un segmento RST, prima che nel server sia stata chiamata la
+funzione \func{accept}.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=10cm]{img/tcp_client_early_abort}
+ \caption{Un possibile caso di terminazione precoce della connessione.}
+ \label{fig:TCP_early_abort}
+\end{figure}
+
+Benché questo non sia un fatto comune, un evento simile può essere osservato
+con dei server molto occupati. In tal caso, con una struttura del server
+simile a quella del nostro esempio, in cui la gestione delle singole
+connessioni è demandata a processi figli, può accadere che il three way
+handshake venga completato e la relativa connessione abortita subito dopo,
+prima che il padre, per via del carico della macchina, abbia fatto in tempo ad
+eseguire la chiamata ad \func{accept}. Di nuovo si ha una situazione analoga
+a quella illustrata in \figref{fig:TCP_early_abort}, in cui la connessione
+viene stabilita, ma subito dopo si ha una condizione di errore che la chiude
+prima che essa sia stata accettata dal programma.
+
+Questo significa che, oltre alla interruzione da parte di un segnale, che
+abbiamo trattato in \secref{sec:TCP_child_hand} nel caso particolare di
+\const{SIGCHLD}, si possono ricevere altri errori non fatali all'uscita di
+\func{accept}, che come nel caso precedente, necessitano semplicemente la
+ripetizione della chiamata senza che si debba uscire dal programma. In questo
+caso anche la versione modificata del nostro server non sarebbe adatta, in
+quanto uno di questi errori causerebbe la terminazione dello stesso. In Linux
+i possibili errori di rete non fatali, riportati sul socket connesso al
+ritorno di \func{accept}, sono \errcode{ENETDOWN}, \errcode{EPROTO},
+\errcode{ENOPROTOOPT}, \errcode{EHOSTDOWN}, \errcode{ENONET},
+\errcode{EHOSTUNREACH}, \errcode{EOPNOTSUPP} e \errcode{ENETUNREACH}.
+
+Si tenga presente che questo tipo di terminazione non è riproducibile
+terminando il client prima della chiamata ad \func{accept}, come si potrebbe
+fare usando l'opzione \texttt{-w} per introdurre una pausa dopo il lancio del
+demone, in modo da poter avere il tempo per lanciare e terminare una
+connessione usando il programma client. In tal caso infatti, alla terminazione
+del client, il socket associato alla connessione viene semplicemente chiuso,
+attraverso la sequenza vista in \secref{sec:TCP_conn_term}, per cui la
+\func{accept} ritornerà senza errori, e si avrà semplicemente un end-of-file
+al primo accesso al socket. Nel caso di Linux inoltre, anche qualora si
+modifichi il client per fargli gestire l'invio di un segmento di RST alla
+chiusura dal socket (come suggerito da Stevens in \cite{UNP1}), non si ha
+nessun errore al ritorno di \funcd{accept} quanto un errore di
+\errcode{ECONNRESET} al primo tentativo di accesso al socket.
+
+
+
+\subsection{La terminazione precoce del server}
+\label{sec:TCP_server_crash}
+
+Un secondo caso critico è quello in cui si ha una terminazione prococe del
+server, ad esempio perché il programma ha un crash. In tal caso si suppone che
+il processo termini per un errore fatale, cosa che potremo simulare
+inviandogli un segnale di terminazione. La conclusione del processo comporta
+la chiusura di tutti i file descriptor aperti, compresi tutti i socket
+relativi a connessioni stabilite; questo significa che al momento del crollo
+del servizio il client riceverà un FIN dal server in corrispondenza della
+chiusura del socket.
+
+Vediamo allora cosa succede nel nostro caso, facciamo partire una connessione
+con il server e scriviamo una prima riga, poi terminiamo il server con un
+\texttt{C-c}. A questo punto scriviamo una seconda riga e poi un'altra riga
+ancora. Il risultato finale della sessione è il seguente:
+\begin{verbatim}
+[piccardi@gont sources]$ ./echo 192.168.1.141
+Prima riga
+Prima riga
+Seconda riga dopo il C-c
+Altra riga
+[piccardi@gont sources]$
+\end{verbatim}
+
+Come si vede il nostro client, nonostante la connessione sia stata interrotta
+prima dell'invio della seconda riga, non solo accetta di inviarla, ma prende
+anche un'altra riga prima di terminare senza riportare nessun
+errore.
+
+Per capire meglio cosa è successo conviene analizzare il flusso dei pacchetti
+utilizzando un analizzatore di traffico come \cmd{tcpdump}. Il comando
+permette di selezionare, nel treffico di rete generato su una macchina, i
+pacchetti che interessano, stampando a video (o salvando su disco) il loro
+conteuto. Non staremo qui ad entrare nei dettagli dell'uso del programma, che
+sono spiegati dalla pagina di manuale; per l'uso che vogliamo farne quello che
+ci interessa è, posizionandosi sulla macchina che fa da client, selezionare
+tutti i pacchetti che sono diretti o provengono dalla macchina che fa da
+server. In questo modo (posto che non ci siano altre connessioni col server,
+cosa che avremo cura di evitare) tutti i pacchetti rilevati apparterranno alla
+nostra sessione di interrogazione del servizio.
+
+Il comando \cmd{tcpdump} permette selezioni molto complesse, basate sulle
+interfacce su cui passano i pacchetti, sugli indirizzi IP, sulle porte, sulle
+caratteristiche ed il contenuto dei pacchetti stessi, inoltre permette di
+combinare fra loro diversi criteri di selezione con degli operatori logici;
+quando un pacchetto che corrisponde ai criteri di selezione scelti viene
+rilevato i suoi dati vengono stampati sullo schermo (anche questi secondo un
+formato configurabile in maniera molto precisa).
+
+Lanciando il comando prima di ripetere la sessione di lavoro mostrata
+nell'esempio precedente potremo allora catturare tutti pacchetti scambiati fra
+il client ed il server; i risultati\footnote{in realtà si è ridotta la
+ lunghezza dell'output rispetto al reale tagliando alcuni dati non necessari
+ alla comprensione del flusso.} prodotti in questa occasione da \cmd{tcpdump}
+sono allora i seguenti:
+\begin{verbatim}
+[root@gont gapil]# tcpdump src 192.168.1.141 or dst 192.168.1.141 -N -t
+tcpdump: listening on eth0
+gont.34559 > anarres.echo: S 800922320:800922320(0) win 5840
+anarres.echo > gont.34559: S 511689719:511689719(0) ack 800922321 win 5792
+gont.34559 > anarres.echo: . ack 1 win 5840
+gont.34559 > anarres.echo: P 1:12(11) ack 1 win 5840
+anarres.echo > gont.34559: . ack 12 win 5792
+anarres.echo > gont.34559: P 1:12(11) ack 12 win 5792
+gont.34559 > anarres.echo: . ack 12 win 5840
+anarres.echo > gont.34559: F 12:12(0) ack 12 win 5792
+gont.34559 > anarres.echo: . ack 13 win 5840
+gont.34559 > anarres.echo: P 12:37(25) ack 13 win 5840
+anarres.echo > gont.34559: R 511689732:511689732(0) win 0
+\end{verbatim}
+
+Le prime tre righe vengono prodotte al momento in cui lanciamo il nostro
+client, e corrispondono ai tre pacchetti del three way handshake. L'output del
+comando riporta anche i numeri di sequenza iniziali, mentre la lettera
+\texttt{S} indica che per quel pacchetto si aveva il SYN flag attivo. Si noti
+come a partire dal secondo pacchetto sia sempre attivo il campo \texttt{ack},
+seguito dal numero di sequenza per il quale si da il ricevuto; quest'ultimo, a
+partire dal terzo pacchetto, viene espresso in forma relativa per maggiore
+compattezza. Il campo \texttt{win} in ogni riga indica la \textit{advertising
+ window} di cui parlavamo in \secref{sec:TCP_TCP_opt}. Allora si può
+verificare dall'output del comando come venga appunto realizzata la sequenza
+di pacchetti descritta in \secref{sec:TCP_conn_cre}: prima viene inviato dal
+clinet un primo pacchetto con il SYN che inizia la connessione, a cui il
+server risponde dando il ricevuto con un secondo pacchetto, che a sua volta
+porta un SYN, cui il client risponde con un il terzo pacchetto di ricevuto.
+
+Ritorniamo allora alla nostra sessione con il servizio echo: dopo le tre righe
+del three way handshake non avremo nulla fin tanto che non scriveremo una
+prima riga sul client; al momento in cui facciamo questo si genera una
+sequenza di altri quattro pacchetti. Il primo, dal client al server,
+contraddistinto da una lettera \texttt{P} che significa che il flag PSH è
+impostato, contiene la nostra riga (che è appunto di 11 caratteri), e ad esso
+il server risponde immediatamente con un pacchetto vuoto di ricevuto. Poi
+tocca al server riscrivere indietro quanto gli è stato inviato, per cui sarà
+lui a mandare indietro un terzo pacchetto con lo stesso contenuto appena
+ricevuto, e a sua volta riceverà dal client un ACK nel quarto pacchetto.
+Questo causerà la ricezione dell'eco nel client che lo stamperà a video.
+
+A questo punto noi procediamo ad interrompere l'esecuzione del server con un
+\texttt{C-c} (cioè con l'invio di \const{SIGTERM}): nel momento in cui
+facciamo questo vengono immediatamente generati altri due pacchetti. La
+terminazione del processo infatti comporta la chiusura di tutti i suoi file
+descriptor, il che comporta, per il socket che avevamo aperto, l'inizio della
+sequenza di chiusura illustrata in \secref{sec:TCP_conn_term}. Questo
+significa che dal server partirà un FIN, che è appunto il primo dei due
+pacchetti, contraddistinto dalla lettera \texttt{F}, cui seguirà al solito un
+ACK da parte del client. A questo punto la connessione dalla parte del server
+è chiusa, ed infatti se usiamo \cmd{netstat} per controllarne lo stato sul
+client, otterremo che essa è andata nello stato \texttt{CLOSE\_WAIT}:
+\begin{verbatim}
+[root@gont gapil]# netstat -ant
+Active Internet connections (servers and established)
+Proto Recv-Q Send-Q Local Address Foreign Address State
+... ... ... ... ... ...
+tcp 1 0 192.168.1.2:34582 192.168.1.141:7 CLOSE_WAIT
+\end{verbatim}
+
+Il problema è che in questo momento il client è bloccato dentro la funzione
+\texttt{ClientEcho} nella chiamata a \func{fgets}, e sta attendendo dell'input
+dal terminale, per cui non è in grado di accorgersi di nulla. Solo quando
+inseriremo la seconda riga il comando uscirà da \func{fgets} e proverà a
+scriverla sul socket. Questo comporta la generazione degli ultimi due
+pacchetti riportati da \cmd{tcpdump}: il primo, inviato dal client contenente
+i 25 caratteri della riga appena letta, e ad esso la macchina server
+risponderà, non essendoci più niente in ascolto sulla porta 7, con un segmento
+di RST, contraddistinto dalla lettera \texttt{R}, che causa la conclusione
+definitiva della connessione anche nel client, dove non comparrà più
+nell'output di \cmd{netstat}.
+
+Non avendo controllato lo stato di uscita della nostra funzione di scrittura
+(si riveda il codice illustrato in \secref{fig:TCP_client_echo_sub}) che a
+questo punto riporterebbe un errore, il client proseguirà leggendo dal socket,
+e dato che questo è stato chiuso avremo che, come spiegato in
+\secref{sec:TCP_conn_term}, la funzione \func{read} ritorna normalmente con un
+valore nullo. Questo comporta che la seguente chiamata a \func{fputs} non ha
+effetto (viene stampata una stringa nulla) ed il client si blocca di nuovo
+nella successiva chiamata a \func{fgets}. Per questo diventa possibile
+inserire una terza riga e solo dopo averlo fatto si avrà la terminazione del
+programma.
+
+Per capire come questa avvenga comunque, non avendo inserito nel codice nessun
+controllo di errore, occorre ricordare che, a parte la bidirezionalità del
+flusso dei dati, dal punto di vista del funzionamento nei confronti delle
+funzioni di lettura e scrittura, i socket sono del tutto analoghi a delle
+pipe. Allora, da quanto illustrato in \secref{sec:ipc_pipes}, sappiamo che
+tutte le volte che si cerca di scrivere su una pipe il cui altro capo non è
+aperto il lettura il processo riceve un segnale di \const{SIGPIPE}, e questo è
+esattamente quello che avviene in questo caso, e siccome non abbiamo un
+gestore per questo segnale, viene eseguita l'azione preimpostata, che è quella
+di terminare il processo.
+
+
+
+
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: