Versione finale del client ECHO su TCP, con esempio di uso della funzione
[gapil.git] / tcpsockadv.tex
index 24c45d2cbf9d1aa707fec08f248fbb4e5703530e..d22c6aa84ab43a5696de32e2346915e11a11424c 100644 (file)
 \label{cha:TCP_advanced}
 
 Esamineremo in questo capitolo le funzionalità più evolute della gestione dei
 \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
 \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
 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
 
 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{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,
 
 
 \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
+\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 per dei normali file, o anche per delle pipe, la condizione di essere
 \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 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} quando viene passato come membro di uno dei tre
-\textit{file descriptor set} usati da \func{select}.
+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) è
 
 Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
 che un socket (che sarà riportato nel primo insieme di file descriptor) è
@@ -80,8 +82,8 @@ pronto per la lettura sono le seguenti:
     \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
     \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
-    connessiioni, potrà bloccarsi.}
+    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
 \end{itemize*}
 
 Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
@@ -109,14 +111,14 @@ Infine c'
 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
 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_outofband}.
+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
 
 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 come il riconoscimento
-della presenza di connessioni pronte, in modo da consentire 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.
+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
 
 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
@@ -129,29 +131,174 @@ quando c'
   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
   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 quando 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 letto.}
-
-
-
-
-\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_outofband}
-
-Una caratteristica speciale dei socket TCP è quella della presenza dei
-cosiddetti dati \textit{out-of-band}
-
+  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}}
 
 
 \subsection{La funzione \func{shutdown}}
@@ -175,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
 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}