+Nella funzione si è anche inserita la possibilità (\texttt{\small 7--14}) di
+inviare dei messaggi di debug (abilitabile con l'uso dell'opzione \texttt{-d}
+che imposta opportunamente \var{debugging}), gestendo entrambi i casi in cui
+la stampa deve essere effettuata tramite \func{syslog} (\texttt{\small 11}) o
+direttamente sullo standard output (\texttt{\small 13}).
+
+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 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 tutte le 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 \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} della nostra libreria personale, 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, il fatto 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 cui alla fine dell'esecuzione del
+gestore il programma, se questo ritorna, l'esecuzione del programma riprenderà
+con l'uscita dalla system call con un errore di \errcode{EINTR}.
+
+Questo comporta che quando si chiude il client, con la terminazione del
+processo figlio, il padre, che riceve il segnale ed esegue il gestore,
+ritornerà dalla \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}, terminando a sua volta con un errore del tipo:
+\begin{verbatim}
+[root@gont sources]# ./echod -i
+accept error: Interrupted system call
+\end{verbatim}%#
+
+
+Come accennato in \secref{sec:sig_gen_beha} questo ci mette di fronte a due
+possibili soluzioni, la più semplice è quella 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} come mostrato in
+\figref{fig:sig_SignalRestart_code}.
+
+\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 delle system call interrotte.}
+ \label{fig:sig_SignalRestart_code}
+\end{figure}
+
+Come si può notare questa funzione è identica a \func{Signal}, 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}, ed
+ alcuni non fanno ripartire neanche \func{accept} e \func{recvfrom}; nel caso
+ di Linux questa è disponibile.} anche quando questa è presente, non è detto
+possa essere usata con \func{accept}. La portabilità però viene al costo di
+una riscrittura parziale del server, secondo quanto mostrato in
+\figref{fig:TCP_echo_server_code}.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/TCP_echod.c}
+ \end{minipage}
+ \normalsize
+ \caption{Codice del corpo principale della seconda versione del server
+ per il servizio \textit{echo}.}
+ \label{fig:TCP_echo_server_code}
+\end{figure}
+
+
+
+
+
+\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 correttamente 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.