Versione finale del client ECHO su TCP, con esempio di uso della funzione
[gapil.git] / tcpsockadv.tex
index 81c37eb5bc981d8f912ea56cdb414f7e10634040..d22c6aa84ab43a5696de32e2346915e11a11424c 100644 (file)
 \label{cha:TCP_advanced}
 
 Esamineremo in questo capitolo le funzionalità più evolute della gestione dei
-socket TCP. 
+socket TCP, come l'uso del I/O multiplexing (trattato in
+\secref{sec:file_multiplexing}) con i socket, l'uso delle opzioni dei socket e
+la gestione dei dati urgenti e \textit{out-of-band}.
 
 
 
-\section{Socket multiplexing}
+\section{Socket I/O multiplexing}
 \label{sec:TCP_sock_multiplexing}
 
 Affronteremo in questa sezione l'utilizzo dell'I/O multiplexing, affrontato in
 \secref{sec:file_multiplexing}, nell'ambito delle applicazioni di rete. Già in
-\ref{sec:TCP_server_crash} era emerso il problema relativo al client del
+\secref{sec:TCP_server_crash} era emerso il problema relativo al client del
 servizio echo che non era in grado di accorgersi della terminazione precoce
-del server essendo bloccato nella lettura dei dati immessi da tastiera.
+del server, essendo bloccato nella lettura dei dati immessi da tastiera.
 
 Abbiamo visto in \secref{sec:file_multiplexing} quali sono le funzionalità del
 sistema che ci permettono di tenere sotto controllo più file descriptor in
 contemporanea; in quella occasione non abbiamo fatto esempi, in quanto quando
-si tratta con file normali questa tipologia di I/O non viene usata, è invece
-un caso tipico delle applicazioni di rete quello di dover gestire varie
-connessioni da cui possono arrivare dati comuni in maniera asincrona, per cui
-riprenderemo l'argomento in questa sezione.
+si tratta con file normali questa tipologia di I/O normalmente non viene
+usata, è invece un caso tipico delle applicazioni di rete quello di dover
+gestire varie connessioni da cui possono arrivare dati comuni in maniera
+asincrona, per cui riprenderemo l'argomento in questa sezione.
 
 
-
-\subsection{La funzione \func{select} con i socket.}
+\subsection{Il comportamento della funzione \func{select} con i socket.}
 \label{sec:TCP_sock_select}
 
-
-
-
 Iniziamo con la prima delle funzioni usate per l'I/O multiplexing,
-\func{select}, il suo funzionamento è già stato descritto in dettaglio in
-\secref{sec:file_multiplexing}; e sappiamo che la funzione ritorna quando uno
-o più dei file descriptor messi sotto controllo è pronto per la relativa
-operazione. 
+\func{select}; il suo funzionamento è già stato descritto in dettaglio in
+\secref{sec:file_multiplexing} e non staremo a ripetere quanto detto lì; 
+sappiamo che la funzione ritorna quando uno o più dei file descriptor messi
+sotto controllo è pronto per la relativa operazione.
 
 In quell'occasione non abbiamo però definito cosa si intende per pronto,
-infatti se per dei normali file, o anche per delle pipe, la condizione di
-essere pronti per la lettura o la scrittura è ovvia, lo è un po' meno di meno
-nel caso dei socket, visto che intervengono tutte le possibili condizioni
-dovute alla rete. Occorre allora specificare quali sono le condizioni in cui
-un socket risulta \textsl{pronto}.
-
-
-
-
-
-\section{Le opzioni dei socket}
-\label{sec:TCP_sock_options}
-
-Dato che la maggior parte delle opzioni dei socket sono relative ai socket
-TCP, ed hanno poi significato analogo quando usate con altri socket,
-tratteremo qui l'argomento in generale.
-
-
-
-\section{I dati \textit{out-of-band}}
-\label{sec:TCP_outofband}
-
-Una caratteristica speciale dei socket TCP è quella della presenza dei
-cosiddetti dati \textit{out-of-band}
-
+infatti per dei normali file, o anche per delle pipe, la condizione di essere
+pronti per la lettura o la scrittura è ovvia; invece lo è molto meno nel caso
+dei socket, visto che possono intervenire tutte una serie di possibili
+condizioni di errore dovute alla rete. Occorre allora specificare chiaramente
+quali sono le condizioni per cui un socket risulta essere ``\textsl{pronto}''
+quando viene passato come membro di uno dei tre \textit{file descriptor set}
+usati da \func{select}.
+
+Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
+che un socket (che sarà riportato nel primo insieme di file descriptor) è
+pronto per la lettura sono le seguenti:
+\begin{itemize*}
+\item nel buffer di ricezione del socket sono arrivati dei dati in quantità
+  sufficiente a superare il valore di una \textsl{soglia di basso livello} (il
+  cosiddetto \textit{low watermark}). Questo valore è espresso in numero di
+  byte e può essere impostato con l'opzione del socket \const{SO\_RCVLOWAT}
+  (tratteremo le opzioni dei socket in \secref{sec:TCP_sock_options}); il suo
+  valore di default è 1 per i socket TCP e UDP. In questo caso una operazione
+  di lettura avrà successo e leggerà un numero di byte maggiore di zero.
+\item il lato in lettura della connessione è stato chiuso; si è cioè ricevuto
+  un segmento FIN (si ricordi quanto illustrato in \secref{sec:TCP_conn_term})
+  sulla connessione. In questo caso una operazione di lettura avrà successo,
+  ma non risulteranno presenti dati (in sostanza \func{read} ritornerà con un
+  valore nullo) per indicare la condizione di end-of-file.
+\item c'è stato un errore sul socket. In questo caso una operazione di lettura
+  non si bloccherà ma restituirà una condizione di errore (ad esempio
+  \func{read} restituirà -1) e imposterà la variabile \var{errno} al relativo
+  valore. Vedremo in \secref{sec:TCP_sock_options} come sia possibile estrarre
+  e cancellare errori pendenti su un socket usando l'opzione
+  \const{SO\_ERROR}.
+\item quando si sta utilizzando un \textit{listening socket} ed ci sono delle
+  connessioni completate. In questo caso la funzione \func{accept} non si
+  bloccherà.\footnote{in realtà questo non è sempre vero, come accennato in
+    \secref{sec:TCP_conn_early_abort} una connessione può essere abortita
+    dalla ricezione di un segmento RST una volta che è stata completata,
+    allora se questo avviene dopo che \func{select} è ritornata, ma prima
+    della chiamata ad \func{accept}, quest'ultima, in assenza di altre
+    connessioni, potrà bloccarsi.}
+\end{itemize*}
+
+Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
+che un socket (che sarà riportato nel secondo insieme di file descriptor) è
+pronto per la scrittura sono le seguenti:
+\begin{itemize*}
+\item nel buffer di invio è disponibile una quantità di spazio superiore al
+  valore della \textsl{soglia di basso livello} in scrittura ed inoltre o il
+  socket è già connesso o non necessita (ad esempio è UDP) di connessione.  Il
+  valore della soglia è espresso in numero di byte e può essere impostato con
+  l'opzione del socket \const{SO\_SNDLOWAT}; il suo valore di default è 2048
+  per i socket TCP e UDP. In questo caso una operazione di scrittura non si
+  bloccherà e restituirà un valore positivo pari al numero di byte accettati
+  dal livello di trasporto.
+\item il lato in scrittura della connessione è stato chiuso. In questo caso
+  una operazione di scrittura sul socket genererà il segnale \const{SIGPIPE}.
+\item c'è stato un errore sul socket. In questo caso una operazione di
+  scrittura non si bloccherà ma restituirà una condizione di errore ed
+  imposterà opportunamente la variabile \var{errno}. Vedremo in
+  \secref{sec:TCP_sock_options} come sia possibile estrarre e cancellare
+  errori pendenti su un socket usando l'opzione \const{SO\_ERROR}.
+\end{itemize*}
+
+Infine c'è una sola condizione che fa si che \func{select} ritorni segnalando
+che un socket (che sarà riportato nel terzo insieme di file descriptor) ha una
+condizione di eccezione pendente, e cioè la ricezione sul socket di dati
+\textsl{fuori banda} (o \textit{out-of-band}), una caratteristica specifica
+dei socket TCP su cui torneremo in \secref{sec:TCP_urgent_data}.
+
+Si noti come nel caso della lettura \func{select} si applichi anche ad
+operazioni che non hanno nulla a che fare con l'I/O di dati come il
+riconoscimento della presenza di connessioni pronte, in modo da consentire
+anche l'utilizzo di \func{accept} in modalità non bloccante. Si noti infine
+come in caso di errore un socket venga sempre riportato come pronto sia per la
+lettura che per la scrittura.
+
+Lo scopo dei due valori di soglia per i buffer di ricezione e di invio è
+quello di consentire maggiore flessibilità nell'uso di \func{select} da parte
+dei programmi, se infatti si sa che una applicazione non è in grado di fare
+niente fintanto che non può ricevere o inviare una certa quantità di dati, si
+possono utilizzare questi valori per far si che \func{select} ritorni solo
+quando c'è la certezza di avere dati a sufficienza.\footnote{questo tipo di
+  controllo è utile di norma solo per la lettura, in quanto in genere le
+  operazioni di scrittura sono già controllate dall'applicazione, che sà
+  sempre quanti dati invia, mentre non è detto possa conoscere la quantità di
+  dati in ricezione; per cui, nella situazione in cui si conosce almeno un
+  valore minimo, per evitare la penalizzazione dovuta alla ripetizione delle
+  operazioni di lettura per accumulare dati sufficienti, si può lasciare al
+  kernel il compito di impostare un minimo al di sotto del quale il file
+  descriptor, pur avendo disponibili dei dati, non viene dato per pronto in
+  lettura.}
+
+
+
+\subsection{Un esempio di I/O multiplexing}
+\label{sec:TCP_multiplex_example}
+
+Abbiamo incontrato la problematica tipica che conduce all'uso dell'I/O
+multiplexing nella nostra analisi degli errori in
+\secref{sec:TCP_conn_early_abort}, quando il nostro client non era in grado di
+rendersi conto di errori sulla connessione essendo impegnato nella attesa di
+dati in ingresso dallo standard input.
+
+In questo caso il problema è quello di dover tenere sotto controllo due
+diversi file descriptor, lo standard input, da cui viene letto il testo che
+vogliamo inviare al server, e il socket connesso con il server su cui detto
+testo sarà scritto e dal quale poi si vorrà ricevere la risposta. L'uso
+dell'I/O multiplexing consente di tenere sotto controllo entrambi, senza
+restare bloccati.
+
+Nel nostro caso quello che ci interessa è non essere bloccati in lettura sullo
+standard input in caso di errori sulla connessione o chiusura della stessa da
+parte del server. Entrambi questi casi possono essere rilevati usando
+\func{select}, per quanto detto in \secref{sec:TCP_sock_select}, mettendo
+sotto osservazione i file descriptor per la condizione di essere pronti in
+lettura: sia infatti che si ricevano dati, che la connessione sia chiusa
+regolarmente (con la ricezione di un segmento FIN) che si riceva una
+condizione di errore (con un segmento RST) il socket connesso sarà pronto in
+lettura (nell'ultimo caso anche in scrittura, ma questo non è necessario ai
+nostri scopi).
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/ClientEcho_third.c}
+  \end{minipage} 
+  \normalsize
+  \caption{La sezione nel codice della terza versione della funzione
+    \func{ClientEcho} usata dal client per il servizio \textit{echo}
+    modificata per l'uso di \func{select}.}
+  \label{fig:TCP_ClientEcho_third}
+\end{figure}
+
+Riprendiamo allora il codice del client, modificandolo per l'uso di
+\func{select}. Quello che dobbiamo modificare è la funzione \func{ClientEcho}
+di \figref{fig:TCP_ClientEcho_second}, dato che tutto il resto, che riguarda
+le modalità in cui viene stabilita la connessione con il server, resta
+assolutamente identico. La nostra nuova versione di \func{ClientEcho}, la
+terza della serie, è riportata in \figref{fig:TCP_ClientEcho_third}, il codice
+completo si trova nel file \file{TCP\_echo\_third.c} dei sorgenti allegati alla
+guida.
+
+In questo caso la funzione comincia (\texttt{\small 8--9}) con l'azzeramento
+del file descriptor set \var{fset} e l'impostazione del valore \var{maxfd}, da
+passare a \func{select} come massimo per il numero di file descriptor. Per
+determinare quest'ultimo si usa la macro \code{max} definita nel nostro file
+\file{macro.h} che raccoglie una collezione di macro di preprocessore di varia
+utilità.
+
+La funzione prosegue poi (\texttt{\small 10--41}) con il ciclo principale, che
+viene ripetuto indefinitamente. Per ogni ciclo si reinizializza
+(\texttt{\small 11--12}) il file descriptor set, impostando i valori per il
+file descriptor associato al socket \var{socket} e per lo standard input (il
+cui valore si recupera con la funzione \func{fileno}). Questo è necessario in
+quanto la successiva (\texttt{\small 13}) chiamata a \func{select} comporta
+una modifica dei due bit relativi, che quindi devono essere reimpostati
+all'inizio di ogni ciclo.
+
+Si noti come la chiamata a \func{select} venga eseguita usando come primo
+argomento il valore di \var{maxfd}, precedentemente calcolato, e passando poi
+il solo file descriptor set per il controllo dell'attività in lettura, negli
+altri argomenti sono passati tutti puntatori nulli, non interessando né il
+controllo delle altre attività, né l'impostazione di un valore di timeout.
+
+Al ritorno di \func{select} si provvede a controllare quale dei due file
+descriptor presenta attività in lettura, cominciando (\texttt{\small 14--24})
+con il file descriptor associato allo standard input. In caso di attività
+(quando cioè \macro{FD\_ISSET} ritorna una valore diverso da zero) si esegue
+(\texttt{\small 15}) una \func{fgets} per leggere gli eventuali dati presenti;
+se non ve ne sono (e la funzione restituisce pertanto un puntatore nullo) si
+ritorna immediatamente (\texttt{\small 16}) dato che questo significa che si è
+chiuso lo standard input e quindi concluso l'utilizzo del client; altrimenti
+(\texttt{\small 18--22}) si scrivono i dati appena letti sul socket,
+prevedendo una uscita immediata in caso di errore di scrittura.
+
+Controllato lo standard input si passa a controllare (\texttt{\small 25--40})
+il socket connesso, in caso di attività (\texttt{\small 26}) si esegue subito
+una \func{read} di cui si controlla il valore di ritorno; se questo è negativo
+(\texttt{\small 27--30}) si è avuto un errore e pertanto si esce
+immediatamente segnalandolo, se è nullo (\texttt{\small 31--34}) significa che
+il server ha chiuso la connessione, e di nuovo si esce con stampando prima un
+messaggio di avviso, altrimenti (\texttt{\small 35--39}) si effettua la
+terminazione della stringa e la si stampa a sullo standard output (uscendo in
+caso di errore), per ripetere il ciclo da capo.
+
+Con questo meccanismo il programma invece di essere bloccato in lettura sullo
+standard input resta bloccato sulla \func{select}, che ritorna soltanto quando
+viene rilevata attività su uno dei due file descriptor posti sotto controllo.
+Questo di norma avviene solo quando si è scritto qualcosa sullo standard
+input, o quando si riceve dal socket la risposta a quanto si era appena
+scritto. Ma adesso il client diventa capace di accorgersi immediatamente della
+terminazione del server; in tal caso infatti il server chiuderà il socket
+connesso, ed alla ricezione del FIN la funzione \func{select} ritornerà (come
+illustrato in \secref{sec:TCP_sock_select}) segnalando una condizione di end
+of file, per cui il nostro client potrà uscire immediatamente.
+
+Riprendiamo la situazione affrontata in \secref{sec:TCP_server_crash},
+terminando il server durante una connessione, in questo caso quello che
+otterremo, una volta scritta una prima riga ed interrotto il server con un
+\texttt{C-c}, sarà:
+\begin{verbatim}
+[piccardi@gont sources]$ ./echo 192.168.1.1
+Prima riga
+Prima riga
+EOF sul socket
+\end{verbatim}%$
+dove l'ultima riga compare immediatamente dopo aver interrotto il server. Il
+nostro client infatti è in grado di accorgersi immediatamente che il socket
+connesso è stato chiuso ed uscire immediatamente.
+
+Veniamo allora agli altri scenari di terminazione anomala visti in
+\secref{sec:TCP_conn_crash}. Il primo di questi è l'interruzione fisica della
+connessione; in questo caso avremo un comportamento analogo al precedente, in
+cui si scrive una riga e non si riceve risposta dal server e non succede
+niente fino a quando non si riceve un errore di \errcode{EHOSTUNREACH} o
+\errcode{ETIMEDOUT} a seconda dei casi.
+
+La differenza è che stavolta potremo scrivere più righe dopo l'interruzione,
+in quanto il nostro client dopo aver inviato i dati non si bloccherà più nella
+lettura dal socket, ma nella \func{select}; per questo potrà accettare
+ulteriore dati che scriverà di nuovo sul socket, fintanto che c'è spazio sul
+buffer di uscita (ecceduto il quale si bloccherà in scrittura). Si ricordi
+infatti che il client non ha modo di determinare se la connessione è attiva o
+meno (dato che in molte situazioni reali l'inattività può essere temporanea).
+Tra l'altro se si ricollega la rete prima della scadenza del timeout, potremo
+anche verificare come tutto quello che si era scritto viene poi effettivamente
+trasmesso non appena la connessione ridiventa attiva, per cui otterremo
+qualcosa del tipo:
+\begin{verbatim}
+[piccardi@gont sources]$ ./echo 192.168.1.1
+Prima riga
+Prima riga
+Seconda riga dopo l'interruzione
+Terza riga
+Quarta riga
+Seconda riga dopo l'interruzione
+Terza riga
+Quarta riga
+\end{verbatim}
+in cui, una volta riconnessa la rete, tutto quello che abbiamo scritto durante
+il periodo di disconnessione restituito indietro e stampato immediatamente.
+
+Lo stesso comportamento visto in \secref{sec:TCP_server_crash} si riottiene
+nel caso di un crollo completo della macchina su cui sta il server. In questo
+caso di nuovo il client non è in grado di accorgersi di niente dato che si
+suppone che il programma server non venga terminato correttamente, ma si
+blocchi tutto senza la possibilità di avere l'emissione di un segmento FIN che
+segnala la terminazione della connessione. Di nuovo fintanto che la
+connessione non si riattiva )con il riavvio della macchina del server) il
+client non è in grado di fare altro che accettare dell'input e tentare di
+inviarlo. La differenza in questo caso è che non appena la connessione
+ridiventa attiva i dati verranno sì trasmessi, ma essendo state perse tutte le
+informazioni relative alle precedenti connessioni ai tentativi di scrittura
+del client sarà risposto con un segmento RST che provocherà il ritorno di
+\func{select} per la ricezione di un errore di \errcode{ECONNRESET}.
 
 
 \subsection{La funzione \func{shutdown}}
@@ -96,7 +322,198 @@ Questa 
 Il problema che si pone è che se la chiusura del socket è effettuata con la
 funzione \func{close}, come spiegato in \secref{sec:TCP_func_close}, si perde
 ogni possibilità di poter rileggere quanto l'altro capo può continuare a
-scrivere. Per poter permettere allora 
+scrivere. Per poter permettere allora di segnalare che si è concluso con la
+scrittura, continuando al contempo a leggere quanto può provenire dall'altro
+capo del socket si può allora usare la funzione \funcd{shutdown}, il cui
+prototipo è:
+\begin{prototype}{sys/socket.h}
+{int shutdown(int sockfd, int how)}
+
+Chiude un lato della 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{ENOTSOCK}] il file descriptor non corrisponde a un socket.
+  \item[\errcode{ENOTCONN}] il socket non è connesso.
+  \end{errlist}
+  ed inoltre \errval{EBADF}.}
+\end{prototype}
+
+La funzione prende come primo argomento il socket \param{sockfd} su cui si
+vuole operare e come secondo argomento un valore intero \param{how} che indica
+la modalità di chiusura del socket, quest'ultima può prendere soltanto tre
+valori: 
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\macro{SHUT\_RD}] chiude il lato in lettura del socket, non sarà più
+  possibile leggere dati da esso, tutti gli eventuali dati trasmessi
+  dall'altro capo del socket saranno automaticamente scartati dal kernel, che,
+  in caso di socket TCP, provvederà comunque ad inviare i relativi segmenti di
+  ACK.
+\item[\macro{SHUT\_WR}] chiude il lato in scrittura del socket, non sarà più
+  possibile scrivere dati su di esso. Nel caso di socket TCP la chiamata causa
+  l'emissione di un segmento FIN, secondo la procedura chiamata
+  \textit{half-close}. Tutti i dati presenti nel buffer di scrittura prima
+  della chiamata saranno inviati, seguiti dalla sequenza di chiusura
+  illustrata in \secref{sec:TCP_conn_term}.
+\item[\macro{SHUT\_RDWR}] chiude sia il lato in lettura che quello in
+  scrittura del socket. È equivalente alla chiamata in sequenza con
+  \macro{SHUT\_RD} e \macro{SHUT\_WR}.
+\end{basedescript}
+
+Ci si può chiedere quale sia l'utilità di avere introdotto \macro{SHUT\_RDWR}
+quando questa sembra rendere \funcd{shutdown} del tutto equivalente ad una
+\func{close}. In realtà non è così, esiste infatti un'altra differenza con
+\func{close}, più sottile. Finora infatti non ci siamo presi la briga di
+sottolineare in maniera esplicita che come per i file e le fifo, anche per i
+socket possono esserci più riferimenti contemporanei ad uno stesso socket. Per
+cui si avrebbe potuto avere l'impressione che sia una corrispondenza univoca
+fra un socket ed il file descriptor con cui vi si accede. Questo non è
+assolutamente vero, (e lo abbiamo già visto nel codice del server di
+\figref{fig:TCP_echo_server_first_code}), ed è invece assolutamente normale
+che, come per gli altri oggetti, ci possano essere più file descriptor che
+fanno riferimento allo stesso socket.
+
+Allora se avviene uno di questi casi quello che succederà è che la chiamata a
+\func{close} darà effettivamente avvio alla sequenza di chiusura di un socket
+soltanto quando il numero di riferimenti a quest'ultimo diventerà nullo.
+Fintanto che ci sono file descriptor che fanno riferimento ad un socket
+\func{close} si limiterà a deallocare nel processo corrente il file descriptor
+utilizzato, ma il socket resterà pienamente accessibile attraverso gli altri
+riferimenti.Se torniamo all'esempio di \figref{fig:TCP_echo_server_first_code}
+abbiamo infatti che le due \func{close} (sul socket connesso nel padre e sul
+socket in ascolto nel figlio), restando comunque altri riferimenti attivi (al
+socket connesso nel figlio e a quello in ascolto nel padre) non effettuano
+nessuna chiusura effettiva.  
+
+Questo non avviene affatto se si usa \func{shutdown} al posto di \func{close},
+in questo caso infatti la chiusura del socket viene effettuata immediatamente,
+indipendentemente dalla presenza di altri riferimenti attivi, e pertanto sarà
+ovviamente efficace anche per tutti gli altri file descriptor con cui si fa
+riferimento allo stesso socket.
+
+Il caso più comune di uso di \func{shutdown} è comunque quello della chiusura
+del lato in scrittura, per segnalare all'altro capo della connessione che si è
+concluso l'invio dei dati, restando comunque in grado di ricevere quanto
+ancora questi potrà inviarci. Questo è ad esempio l'uso che ci serve per
+rendere finalmente completo il nostro esempio sul servizio echo. Il nostro
+client infatti presenta ancora un problema, che nell'uso che finora ne abbiamo
+fatto non è emerso, ma che ci aspetta dietro l'angolo non appena usciamo
+dall'uso interattivo e proviamo ad eseguirlo redirigendo standard input e
+standard output. Così se eseguiamo:
+\begin{verbatim}
+[piccardi@gont sources]$ ./echo 192.168.1.1 < ../fileadv.tex  > copia
+\end{verbatim}%$
+vedremo che il file \texttt{copia} risulta mancare della parte finale.
+
+Per capire cosa avviene in questo caso occorre tenere presente come avviene la
+comunicazione via rete; quando redirigiamo lo standard input il nostro client
+inizierà a leggere il contenuto del file \texttt{../fileadv.tex} a blocchi di
+dimensione massima pari a \texttt{MAXLINE} per poi scriverlo, alla massima
+velocità consentitagli dalla rete, sul socket. Dato che la connessione è con
+una macchina remota occorre un certo tempo perché i pacchetti vi arrivino,
+vengano processati, e poi tornino indietro. Considerando trascurabile il tempo
+di processo, questo tempo, detto RTT (da \textit{Round Trip Time} può essere
+stimato con l'uso del comando \cmd{ping}. Ma mantre il pacchetti sono in
+transito sulla rete il client continua a leggere e a scrivere fintanto che il
+file in ingresso finisce. 
+
+A questo punto, se torniamo al codice mostrato in
+\figref{fig:TCP_ClientEcho_third}, notiamo che non appena viene ricevuto un
+end-of-file in ingresso il nostro client termina. Nel caso interattivo, in cui
+si inviavano brevi stringe una alla volta, c'era sempre il tempo di eseguire
+la lettura completa di quanto il server rimandava indietro. In questo caso
+però quando il client termina, essendo la comunicazione a piena velocità, ci
+saranno ancora pacchetti in transito sulla rete, ma siccome il client esce
+immediatamente dopo la fine del file in ingresso, questi non faranno a tempo a
+completare il percorso e verranno persi.
+
+Per evitare questo tipo di problema occorre, invece di uscire, usare
+\func{shutdown} per effettuare la chiusura del socket in scrittura una volta
+completata la lettura del file in ingresso. In questo modo il client segnalerà
+al server la chiusura del flusso dei dati, ma potrà continuare a leggere
+quanto il server gli sta ancora inviando fino a quando quest'ultimo,
+riconosciuta la chiusura del socket in scrittura da parte del client,
+effettuerà la chiusura dello stesso a sua volta. Solo alla ricezione della
+chiusura del socket da parte del server, si potrà essere sicuri della
+ricezione di tutti i dati prima della terminazione della connessione.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/ClientEcho.c}
+  \end{minipage} 
+  \normalsize
+  \caption{La sezione nel codice della versione finale della funzione
+    \func{ClientEcho}, che usa \func{shutdown} per una conclusione corretta
+    della connessione.}
+  \label{fig:TCP_ClientEcho}
+\end{figure}
+
+Si è allora riportato in \figref{fig:TCP_ClientEcho} la versione finale della
+nostra funzione \func{ClientEcho}, in grado di gestire correttamente l'intero
+flusso di dati fra client e server. Il codice completo del client,
+comprendente la gestione delle opzioni a riga di comando e le istruzioni per
+la creazione della connessione, si trova nel file \file{TCP\_echo.c},
+distribuito coi sorgenti allegati alla guida.
+
+La nuova versione è molto simile alla precedente di
+\figref{fig:TCP_ClientEcho_third}; la prima differenza è l'introduzione
+(\texttt{\small 7}) della variabile \var{eof}, inizializzata ad un valore
+nullo, che serve a mantenere traccia dell'avvenuta conclusione della lettura
+del file in ingresso.
+
+La seconda modifica (\texttt{\small 12--15}) è stata quella di rendere
+subordinato ad un valore nullo di \var{eof} l'impostazione del file descriptor
+set per l'osservazione dello standard input. Se infatti il valore di \var{eof}
+è non nullo significa che si è già raggiunta la fine del file in ingresso ed è
+pertanto inutile continuare a tenere sotto controllo lo standard input nella
+successiva (\texttt{\small 16}) chiamata a \func{select}.
+
+Le maggiori modifiche rispetto alla precedente versione sono invece nella
+gestione (\texttt{\small 18--22}) del caso in cui la lettura con \func{fgets}
+restitisca un valore nullo, indice della fine del file, che prima causava
+l'immediato ritorno della funzione. In questo caso prima (\texttt{\small 19})
+si imposta opportunamente \var{eof} ad un valore non nullo, dopo di che
+(\texttt{\small 20}) si effettua la chiusura del lato in scrittura del socket
+con \func{shutdown}. Infine (\texttt{\small 21}) si usa la macro
+\macro{FD\_CLR} per togliere lo standard input dal file descriptor set.
+
+In questo modo anche se la lettura del file in ingresso è conclusa, la
+funzione non esce dal ciclo principale (\texttt{\small 11--50}), ma continua
+ad eseguirlo ripetendo la chiamata a \func{select} per tenere sotto controllo
+soltanto il socket connesso, dal quale possono arrivare altri dati, che
+saranno letti (\texttt{\small 31}), ed opportunamente trascritti
+(\texttt{\small 44--48}) sullo standard input.
+
+Il ritorno della funzione, e la conseguente terminazione normale del client,
+viene invece adesso gestito all'interno (\texttt{\small 30--49}) della lettura
+dei dati dal socket; se infatti dalla lettura del socket si riceve una
+condizione di end-of-file, la si tratterà (\texttt{\small 36--43}) in maniera
+diversa a seconda del valore di \var{eof}. Se infatti questa è diversa da zero
+(\texttt{\small 37--39}), essendo stata completata la lettura del file in
+ingresso, vorrà dire che anche il server ha concluso la trasmissione dei dati
+restanti, e si potrà uscire senza errori, altrimenti si stamperà
+(\texttt{\small 40--42}) un messaggio di errore per la chiusura precoce della
+connesione.
+
+
+
+\section{Le opzioni dei socket}
+\label{sec:TCP_sock_options}
+
+Dato che la maggior parte delle opzioni dei socket sono relative ai socket
+TCP, ed hanno poi significato analogo quando usate con altri socket, abbiamo
+preferito trattare l'argomento in generale in questa sezione piuttosto che nel
+capitolo dedicato alla trattazione generica dei socket.
+
+
+
+\section{I dati \textit{out-of-band}}
+\label{sec:TCP_urgent_data}
+
+Una caratteristica speciale dei socket TCP è quella della presenza dei
+cosiddetti dati \textit{out-of-band}