+Come si può vedere in questo caso si controlla il valore di ritorno di tutte
+le funzioni, ed inoltre si verifica la presenza di un eventuale end of file in
+caso di lettura. Con questa modifica il nostro client echo diventa in grado di
+accorgersi della chiusura del socket da parte del server, per cui ripetendo la
+sequenza di operazioni precedenti stavolta otterremo che:
+\begin{verbatim}
+[piccardi@gont sources]$ ./echo 192.168.1.141
+Prima riga
+Prima riga
+Seconda riga dopo il C-c
+EOF sul socket
+\end{verbatim}%$
+ma di nuovo si tenga presente che non c'è modo di accorgersi della chiusura
+del socket fin quando non si esegue la scrittura della seconda riga; il
+protocollo infatti prevede che ci debba essere una scrittura prima di ricevere
+un RST che confermi la chiusura del file, e solo alle successive scritture si
+potrà ottenere un errore.
+
+Questa caratteristica dei socket ci mette di fronte ad un altro problema
+relativo al nostro client, e che cioè esso non è in grado di accorgersi di
+nulla fintanto che è bloccato nella lettura del terminale fatta con
+\func{gets}. In questo caso il problema è minimo, ma esso riemergerà più
+avanti, ed è quello che si deve affrontare tutte le volte quando si ha a che
+fare con la necessità di lavorare con più descrittori, nel qual caso diventa
+si pone la questione di come fare a non restare bloccati su un socket quando
+altri potrebbero essere liberi. Vedremo come affrontare questa problematica in
+sez.~\ref{sec:TCP_sock_multiplexing}.
+
+
+\subsection{Altri scenari di terminazione della connessione}
+\label{sec:TCP_conn_crash}
+
+La terminazione del server è solo uno dei possibili scenari di terminazione
+della connessione, un altro caso è ad esempio quello in cui si ha un crollo
+della rete, cosa che potremo simulare facilmente staccando il cavo di rete.
+Un'altra condizione è quella di un blocco della macchina completo della su cui
+gira il server che deve essere riavviata, cosa che potremo simulare sia
+premendo il bottone di reset,\footnote{un normale shutdown non va bene; in tal
+ caso infatti il sistema provvede a terminare tutti i processi, per cui la
+ situazione sarebbe sostanzialmente identica alla precedente.} che, in
+maniera più gentile, riavviando la macchina dopo aver interrotto la
+connessione di rete.
+
+Cominciamo ad analizzare il primo caso, il crollo della rete. Ripetiamo la
+nostra sessione di lavoro precedente, lanciamo il client, scriviamo una prima
+riga, poi stacchiamo il cavo e scriviamo una seconda riga. Il risultato che
+otterremo è:
+\begin{verbatim}
+[piccardi@gont sources]$ ./echo 192.168.1.141
+Prima riga
+Prima riga
+Seconda riga dopo l'interruzione
+Errore in lettura: No route to host
+\end{verbatim}%$
+
+Quello che succede in questo è che il programma, dopo aver scritto la seconda
+riga, resta bloccato per un tempo molto lungo, prima di dare l'errore
+\errcode{EHOSTUNREACH}. Se andiamo ad osservare con \cmd{strace} cosa accade
+nel periodo in cui il programma è bloccato vedremo che stavolta, a differenza
+del caso precedente, il programma è bloccato nella lettura dal socket.
+
+Se poi, come nel caso precedente, usiamo l'accortezza di analizzare il
+traffico di rete fra client e server con \cmd{tcpdump}, otterremo il seguente
+risultato:
+\begin{verbatim}
+[root@gont sources]# tcpdump src 192.168.1.141 or dst 192.168.1.141 -N -t
+tcpdump: listening on eth0
+gont.34685 > anarres.echo: S 1943495663:1943495663(0) win 5840
+anarres.echo > gont.34685: S 1215783131:1215783131(0) ack 1943495664 win 5792
+gont.34685 > anarres.echo: . ack 1 win 5840
+gont.34685 > anarres.echo: P 1:12(11) ack 1 win 5840
+anarres.echo > gont.34685: . ack 12 win 5792
+anarres.echo > gont.34685: P 1:12(11) ack 12 win 5792
+gont.34685 > anarres.echo: . ack 12 win 5840
+gont.34685 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34685 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34685 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34685 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34685 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34685 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34685 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34685 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34685 > anarres.echo: P 12:45(33) ack 12 win 5840
+arp who-has anarres tell gont
+arp who-has anarres tell gont
+arp who-has anarres tell gont
+arp who-has anarres tell gont
+arp who-has anarres tell gont
+arp who-has anarres tell gont
+...
+\end{verbatim}
+
+In questo caso l'andamento dei primi sette pacchetti è esattamente lo stesso
+di prima. Solo che stavolta, non appena inviata la seconda riga, il programma
+si bloccherà nella successiva chiamata a \func{read}, non ottenendo nessuna
+risposta. Quello che succede è che nel frattempo il kernel provvede, come
+richiesto dal protocollo TCP, a tentare la ritrasmissione della nostra riga un
+certo numero di volte, con tempi di attesa crescente fra un tentativo ed il
+successivo, per tentare di ristabilire la connessione.
+
+Il risultato finale qui dipende dall'implementazione dello stack TCP, e nel
+caso di Linux anche dall'impostazione di alcuni dei parametri di sistema che
+si trovano in \file{/proc/sys/net/ipv4}, che ne controllano il comportamento:
+in questo caso in particolare da
+\procrelfile{/proc/sys/net/ipv4}{tcp\_retries2} (vedi
+sez.~\ref{sec:sock_ipv4_sysctl}). Questo parametro infatti specifica il numero
+di volte che deve essere ritentata la ritrasmissione di un pacchetto nel mezzo
+di una connessione prima di riportare un errore di timeout. Il valore
+preimpostato è pari a 15, il che comporterebbe 15 tentativi di ritrasmissione,
+ma nel nostro caso le cose sono andate diversamente, dato che le
+ritrasmissioni registrate da \cmd{tcpdump} sono solo 8; inoltre l'errore
+riportato all'uscita del client non è stato \errcode{ETIMEDOUT}, come dovrebbe
+essere in questo caso, ma \errcode{EHOSTUNREACH}.
+
+Per capire l'accaduto continuiamo ad analizzare l'output di \cmd{tcpdump}:
+esso ci mostra che a un certo punto i tentativi di ritrasmissione del
+pacchetto sono cessati, per essere sostituiti da una serie di richieste di
+protocollo ARP in cui il client richiede l'indirizzo del server.
+
+Come abbiamo accennato in sez.~\ref{sec:net_tcpip_general} ARP è il protocollo
+che si incarica di trovare le corrispondenze fra indirizzo IP e indirizzo
+hardware sulla scheda di rete. È evidente allora che nel nostro caso, essendo
+client e server sulla stessa rete, è scaduta la voce nella \textit{ARP
+ cache}\footnote{la \textit{ARP cache} è una tabella mantenuta internamente
+ dal kernel che contiene tutte le corrispondenze fra indirizzi IP e indirizzi
+ fisici, ottenute appunto attraverso il protocollo ARP; le voci della tabella
+ hanno un tempo di vita limitato, passato il quale scadono e devono essere
+ nuovamente richieste.} relativa ad \texttt{anarres}, ed il nostro client ha
+iniziato ad effettuare richieste ARP sulla rete per sapere l'IP di
+quest'ultimo, che essendo scollegato non poteva rispondere. Anche per questo
+tipo di richieste esiste un timeout, per cui dopo un certo numero di tentativi
+il meccanismo si è interrotto, e l'errore riportato al programma a questo
+punto è stato \errcode{EHOSTUNREACH}, in quanto non si era più in grado di
+contattare il server.
+
+Un altro errore possibile in questo tipo di situazione, che si può avere
+quando la macchina è su una rete remota, è \errcode{ENETUNREACH}; esso viene
+riportato alla ricezione di un pacchetto ICMP di \textit{destination
+ unreachable} da parte del router che individua l'interruzione della
+connessione. Di nuovo anche qui il risultato finale dipende da quale è il
+meccanismo più veloce ad accorgersi del problema.
+
+Se però agiamo sui parametri del kernel, e scriviamo in \file{tcp\_retries2}
+un valore di tentativi più basso, possiamo evitare la scadenza della
+\textit{ARP cache} e vedere cosa succede. Così se ad esempio richiediamo 4
+tentativi di ritrasmissione, l'analisi di \cmd{tcpdump} ci riporterà il
+seguente scambio di pacchetti:
+\begin{verbatim}
+[root@gont gapil]# tcpdump src 192.168.1.141 or dst 192.168.1.141 -N -t
+tcpdump: listening on eth0
+gont.34752 > anarres.echo: S 3646972152:3646972152(0) win 5840
+anarres.echo > gont.34752: S 2735190336:2735190336(0) ack 3646972153 win 5792
+gont.34752 > anarres.echo: . ack 1 win 5840
+gont.34752 > anarres.echo: P 1:12(11) ack 1 win 5840
+anarres.echo > gont.34752: . ack 12 win 5792
+anarres.echo > gont.34752: P 1:12(11) ack 12 win 5792
+gont.34752 > anarres.echo: . ack 12 win 5840
+gont.34752 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34752 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34752 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34752 > anarres.echo: P 12:45(33) ack 12 win 5840
+gont.34752 > anarres.echo: P 12:45(33) ack 12 win 5840
+\end{verbatim}
+e come si vede in questo caso i tentativi di ritrasmissione del pacchetto
+iniziale sono proprio 4 (per un totale di 5 voci con quello trasmesso la prima
+volta), ed in effetti, dopo un tempo molto più breve rispetto a prima ed in
+corrispondenza dell'invio dell'ultimo tentativo, quello che otterremo come
+errore all'uscita del client sarà diverso, e cioè:
+\begin{verbatim}
+[piccardi@gont sources]$ ./echo 192.168.1.141
+Prima riga
+Prima riga
+Seconda riga dopo l'interruzione
+Errore in lettura: Connection timed out
+\end{verbatim}%$
+che corrisponde appunto, come ci aspettavamo, alla ricezione di un
+\errcode{ETIMEDOUT}.
+
+Analizziamo ora il secondo scenario, in cui si ha un crollo della macchina che
+fa da server. Al solito lanciamo il nostro client, scriviamo una prima riga
+per verificare che sia tutto a posto, poi stacchiamo il cavo e riavviamo il
+server. A questo punto, ritornato attivo il server, scriviamo una seconda
+riga. Quello che otterremo in questo caso è:
+\begin{verbatim}
+[piccardi@gont sources]$ ./echo 192.168.1.141
+Prima riga
+Prima riga
+Seconda riga dopo l'interruzione
+Errore in lettura Connection reset by peer
+\end{verbatim}%$
+e l'errore ricevuti da \func{read} stavolta è \errcode{ECONNRESET}. Se al
+solito riportiamo l'analisi dei pacchetti effettuata con \cmd{tcpdump},
+avremo:
+\begin{verbatim}
+[root@gont gapil]# tcpdump src 192.168.1.141 or dst 192.168.1.141 -N -t
+tcpdump: listening on eth0
+gont.34756 > anarres.echo: S 904864257:904864257(0) win 5840
+anarres.echo > gont.34756: S 4254564871:4254564871(0) ack 904864258 win 5792
+gont.34756 > anarres.echo: . ack 1 win 5840
+gont.34756 > anarres.echo: P 1:12(11) ack 1 win 5840
+anarres.echo > gont.34756: . ack 12 win 5792
+anarres.echo > gont.34756: P 1:12(11) ack 12 win 5792
+gont.34756 > anarres.echo: . ack 12 win 5840
+gont.34756 > anarres.echo: P 12:45(33) ack 12 win 5840
+anarres.echo > gont.34756: R 4254564883:4254564883(0) win 0
+\end{verbatim}
+
+Ancora una volta i primi sette pacchetti sono gli stessi; ma in questo caso
+quello che succede dopo lo scambio iniziale è che, non avendo inviato nulla
+durante il periodo in cui si è riavviato il server, il client è del tutto
+ignaro dell'accaduto per cui quando effettuerà una scrittura, dato che la
+macchina server è stata riavviata e che tutti gli stati relativi alle
+precedenti connessioni sono completamente persi, anche in presenza di una
+nuova istanza del server echo non sarà possibile consegnare i dati in arrivo,
+per cui alla loro ricezione il kernel risponderà con un segmento di RST.
+
+Il client da parte sua, dato che neanche in questo caso non è stato emesso un
+FIN, dopo aver scritto verrà bloccato nella successiva chiamata a \func{read},
+che però adesso ritornerà immediatamente alla ricezione del segmento RST,
+riportando appunto come errore \errcode{ECONNRESET}. Occorre precisare che se
+si vuole che il client sia in grado di accorgersi del crollo del server anche
+quando non sta effettuando uno scambio di dati, è possibile usare una
+impostazione speciale del socket (ci torneremo in
+sez.~\ref{sec:sock_generic_options}) che provvede all'esecuzione di questo
+controllo.
+
+
+\section{L'uso dell'I/O multiplexing}
+\label{sec:TCP_sock_multiplexing}
+
+Affronteremo in questa sezione l'utilizzo dell'I/O multiplexing, affrontato in
+sez.~\ref{sec:file_multiplexing}, nell'ambito delle applicazioni di rete. Già
+in sez.~\ref{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.
+
+Abbiamo visto in sez.~\ref{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 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,
+\func{select}; il suo funzionamento è già stato descritto in dettaglio in
+sez.~\ref{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; 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 \itindex{file~descriptor~set}
+\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 l'uso di questa opzione in sez.~\ref{sec:sock_generic_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
+ sez.~\ref{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 sez.~\ref{sec:sock_generic_options} come sia possibile
+ estrarre e cancellare gli errori pendenti su un socket senza usare
+ \func{read} 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
+ sez.~\ref{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} (trattata in
+ sez.~\ref{sec:sock_generic_options}); 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
+ sez.~\ref{sec:sock_generic_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
+\textsl{dati urgenti} (o \itindex{out-of-band} \textit{out-of-band}), una
+caratteristica specifica dei socket TCP su cui torneremo in
+sez.~\ref{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 sa
+ 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 socket,
+ 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
+sez.~\ref{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 sez.~\ref{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 fig.~\ref{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 fig.~\ref{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 \itindex{file~descriptor~set} \textit{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 \itindex{file~descriptor~set} \textit{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 \itindex{file~descriptor~set} \textit{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 sez.~\ref{sec:TCP_sock_select}) segnalando una condizione di end
+of file, per cui il nostro client potrà uscire immediatamente.
+
+Riprendiamo la situazione affrontata in sez.~\ref{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
+sez.~\ref{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 sez.~\ref{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}}
+\label{sec:TCP_shutdown}
+
+Come spiegato in sez.~\ref{sec:TCP_conn_term} il procedimento di chiusura di un
+socket TCP prevede che da entrambe le parti venga emesso un segmento FIN. È
+pertanto del tutto normale dal punto di vista del protocollo che uno dei due
+capi chiuda la connessione, quando l'altro capo la lascia
+aperta.\footnote{abbiamo incontrato questa situazione nei vari scenari critici
+ di sez.~\ref{sec:TCP_echo_critical}.}
+
+È pertanto possibile avere una situazione in cui un capo della connessione non
+avendo più nulla da scrivere, possa chiudere il socket, segnalando così
+l'avvenuta terminazione della trasmissione (l'altro capo riceverà infatti un
+end-of-file in lettura) mentre dall'altra parte si potrà proseguire la
+trasmissione dei dati scrivendo sul socket che da quel lato è ancora aperto.
+Questa è quella situazione in cui si dice che il socket è \textit{half
+ closed}.
+
+Il problema che si pone è che se la chiusura del socket è effettuata con la
+funzione \func{close}, come spiegato in sez.~\ref{sec:TCP_func_close}, si perde
+ogni possibilità di poter rileggere quanto l'altro capo può continuare a
+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
+ \itindex{half-close} \textit{half-close}. Tutti i dati presenti nel buffer
+ di scrittura prima della chiamata saranno inviati, seguiti dalla sequenza di
+ chiusura illustrata in sez.~\ref{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
+fig.~\ref{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 l'uso
+di \func{close} si limiterà a deallocare nel processo corrente il file
+descriptor utilizzato, ma il socket resterà pienamente accessibile attraverso
+tutti gli altri riferimenti. Se torniamo all'esempio originale del server di
+fig.~\ref{fig:TCP_echo_server_first_code} abbiamo infatti che ci sono due
+\func{close}, una sul socket connesso nel padre, ed una sul socket in ascolto
+nel figlio, ma queste non effettuano nessuna chiusura reale di detti socket,
+dato che restano altri riferimenti attivi, uno al socket connesso nel figlio
+ed uno a quello in ascolto nel padre.
+
+Questo non avviene affatto se si usa \func{shutdown} con argomento
+\macro{SHUT\_RDWR} 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à efficace anche per tutti
+gli altri file descriptor con cui, nello stesso o in altri processi, 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
+questi potrà ancora inviarci. Questo è ad esempio l'uso che ci serve per
+rendere finalmente completo il nostro esempio sul servizio \textit{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 è quello impiegato nella trasmissione via rete, che
+viene detto RTT (dalla denominazione inglese \itindex{Round~Trip~Time}
+\textit{Round Trip Time}) ed è quello che viene stimato con l'uso del comando
+\cmd{ping}.
+
+A questo punto, se torniamo al codice mostrato in
+fig.~\ref{fig:TCP_ClientEcho_third}, possiamo vedere che mentre i pacchetti
+sono in transito sulla rete il client continua a leggere e a scrivere fintanto
+che il file in ingresso finisce. Però non appena viene ricevuto un end-of-file
+in ingresso il nostro client termina. Nel caso interattivo, in cui si
+inviavano brevi stringhe una alla volta, c'era sempre il tempo di eseguire la
+lettura completa di quanto il server rimandava indietro. In questo caso
+invece, quando il client termina, essendo la comunicazione saturata e a piena
+velocità, ci saranno ancora pacchetti in transito sulla rete che devono
+arrivare al server e poi tornare indietro, 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, invece di uscire una volta completata la
+lettura del file in ingresso, occorre usare \func{shutdown} per effettuare la
+chiusura del lato in scrittura del socket. 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 indietro, fino a quando anch'esso,
+riconosciuta la chiusura del socket in scrittura da parte del client,
+effettuerà la chiusura dalla sua parte. Solo alla ricezione della chiusura del
+socket da parte del server il client potrà essere sicuro della ricezione di
+tutti i dati e della terminazione effettiva 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 fig.~\ref{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
+\texttt{TCP\_echo\_fourth.c}, distribuito coi sorgenti allegati alla guida.
+
+La nuova versione è molto simile alla precedente di
+fig.~\ref{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}
+restituisce un valore nullo, indice della fine del file. Questa nella
+precedente versione 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
+\itindex{file~descriptor~set} \textit{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 output.
+
+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
+connessione.
+
+
+\subsection{Un server basato sull'I/O multiplexing}
+\label{sec:TCP_serv_select}
+
+Seguendo di nuovo le orme di Stevens in \cite{UNP1} vediamo ora come con
+l'utilizzo dell'I/O multiplexing diventi possibile riscrivere completamente il
+nostro server \textit{echo} con una architettura completamente diversa, in
+modo da evitare di dover creare un nuovo processo tutte le volte che si ha una
+connessione.\footnote{ne faremo comunque una implementazione diversa rispetto
+ a quella presentata da Stevens in \cite{UNP1}.}
+
+La struttura del nuovo server è illustrata in
+fig.~\ref{fig:TCP_echo_multiplex}, in questo caso avremo un solo processo che
+ad ogni nuova connessione da parte di un client sul socket in ascolto si
+limiterà a registrare l'entrata in uso di un nuovo file descriptor ed
+utilizzerà \func{select} per rilevare la presenza di dati in arrivo su tutti i
+file descriptor attivi, operando direttamente su ciascuno di essi.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=13cm]{img/TCPechoMult}
+ \caption{Schema del nuovo server echo basato sull'I/O multiplexing.}
+ \label{fig:TCP_echo_multiplex}
+\end{figure}
+
+La sezione principale del codice del nuovo server è illustrata in
+fig.~\ref{fig:TCP_SelectEchod}. Si è tralasciata al solito la gestione delle
+opzioni, che è identica alla versione precedente. Resta invariata anche tutta
+la parte relativa alla gestione dei segnali, degli errori, e della cessione
+dei privilegi, così come è identica la gestione della creazione del socket (si
+può fare riferimento al codice già illustrato in
+sez.~\ref{sec:TCPsimp_server_main}); al solito il codice completo del server è
+disponibile coi sorgenti allegati nel file \texttt{select\_echod.c}.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/select_echod.c}
+ \end{minipage}
+ \normalsize
+ \caption{La sezione principale del codice della nuova versione di server
+ \textit{echo} basati sull'uso della funzione \func{select}.}
+ \label{fig:TCP_SelectEchod}
+\end{figure}
+
+In questo caso, una volta aperto e messo in ascolto il socket, tutto quello
+che ci servirà sarà chiamare \func{select} per rilevare la presenza di nuove
+connessioni o di dati in arrivo, e processarli immediatamente. Per
+implementare lo schema mostrato in fig.~\ref{fig:TCP_echo_multiplex}, il
+programma usa una tabella dei socket connessi mantenuta nel vettore
+\var{fd\_open} dimensionato al valore di \const{FD\_SETSIZE}, ed una variabile
+\var{max\_fd} per registrare il valore più alto dei file descriptor aperti.
+
+Prima di entrare nel ciclo principale (\texttt{\small 6--56}) la nostra
+tabella viene inizializzata (\texttt{\small 2}) a zero (valore che
+utilizzeremo come indicazione del fatto che il relativo file descriptor non è
+aperto), mentre il valore massimo (\texttt{\small 3}) per i file descriptor
+aperti viene impostato a quello del socket in ascolto,\footnote{in quanto esso
+ è l'unico file aperto, oltre i tre standard, e pertanto avrà il valore più
+ alto.} che verrà anche (\texttt{\small 4}) inserito nella tabella.
+
+La prima sezione (\texttt{\small 7--10}) del ciclo principale esegue la
+costruzione del \itindex{file~descriptor~set} \textit{file descriptor set}
+\var{fset} in base ai socket connessi in un certo momento; all'inizio ci sarà
+soltanto il socket in ascolto, ma nel prosieguo delle operazioni, verranno
+utilizzati anche tutti i socket connessi registrati nella tabella
+\var{fd\_open}. Dato che la chiamata di \func{select} modifica il valore del
+\itindex{file~descriptor~set} \textit{file descriptor set}, è necessario
+ripetere (\texttt{\small 7}) ogni volta il suo azzeramento, per poi procedere
+con il ciclo (\texttt{\small 8--10}) in cui si impostano i socket trovati
+attivi.
+
+Per far questo si usa la caratteristica dei file descriptor, descritta in
+sez.~\ref{sec:file_open}, per cui il kernel associa sempre ad ogni nuovo file
+il file descriptor con il valore più basso disponibile. Questo fa sì che si
+possa eseguire il ciclo (\texttt{\small 8}) a partire da un valore minimo, che
+sarà sempre quello del socket in ascolto, mantenuto in \var{list\_fd}, fino al
+valore massimo di \var{max\_fd} che dovremo aver cura di tenere aggiornato.
+Dopo di che basterà controllare (\texttt{\small 9}) nella nostra tabella se il
+file descriptor è in uso o meno,\footnote{si tenga presente che benché il
+ kernel assegni sempre il primo valore libero, dato che nelle operazioni i
+ socket saranno aperti e chiusi in corrispondenza della creazione e
+ conclusione delle connessioni, si potranno sempre avere dei \textsl{buchi}
+ nella nostra tabella.} e impostare \var{fset} di conseguenza.
+
+Una volta inizializzato con i socket aperti il nostro \textit{file descriptor
+ set} potremo chiamare \func{select} per fargli osservare lo stato degli
+stessi (in lettura, presumendo che la scrittura sia sempre consentita). Come
+per il precedente esempio di sez.~\ref{sec:TCP_child_hand}, essendo questa
+l'unica funzione che può bloccarsi, ed essere interrotta da un segnale, la
+eseguiremo (\texttt{\small 11--12}) all'interno di un ciclo di \code{while}
+che la ripete indefinitamente qualora esca con un errore di \errcode{EINTR}.
+Nel caso invece di un errore normale si provvede (\texttt{\small 13--16}) ad
+uscire stampando un messaggio di errore.
+
+Se invece la funzione ritorna normalmente avremo in \var{n} il numero di
+socket da controllare. Nello specifico si danno due possibili casi diversi per
+cui \func{select} può essere ritornata: o si è ricevuta una nuova connessione
+ed è pronto il socket in ascolto, sul quale si può eseguire \func{accept} o
+c'è attività su uno dei socket connessi, sui quali si può eseguire
+\func{read}.
+
+Il primo caso viene trattato immediatamente (\texttt{\small 17--26}): si
+controlla (\texttt{\small 17}) che il socket in ascolto sia fra quelli attivi,
+nel qual caso anzitutto (\texttt{\small 18}) se ne decrementa il numero in
+\var{n}; poi, inizializzata (\texttt{\small 19}) la lunghezza della struttura
+degli indirizzi, si esegue \func{accept} per ottenere il nuovo socket connesso
+controllando che non ci siano errori (\texttt{\small 20--23}). In questo caso
+non c'è più la necessità di controllare per interruzioni dovute a segnali, in
+quanto siamo sicuri che \func{accept} non si bloccherà. Per completare la
+trattazione occorre a questo punto aggiungere (\texttt{\small 24}) il nuovo
+file descriptor alla tabella di quelli connessi, ed inoltre, se è il caso,
+aggiornare (\texttt{\small 25}) il valore massimo in \var{max\_fd}.
+
+Una volta controllato l'arrivo di nuove connessioni si passa a verificare se
+vi sono dati sui socket connessi, per questo si ripete un ciclo
+(\texttt{\small 29--55}) fintanto che il numero di socket attivi \var{n} resta
+diverso da zero; in questo modo se l'unico socket con attività era quello
+connesso, avendo opportunamente decrementato il contatore, il ciclo verrà
+saltato, e si ritornerà immediatamente (ripetuta l'inizializzazione del
+\itindex{file~descriptor~set} \textit{file descriptor set} con i nuovi valori
+nella tabella) alla chiamata di \func{accept}. Se il socket attivo non è
+quello in ascolto, o ce ne sono comunque anche altri, il valore di \var{n} non
+sarà nullo ed il controllo sarà eseguito. Prima di entrare nel ciclo comunque
+si inizializza (\texttt{\small 28}) il valore della variabile \var{i} che
+useremo come indice nella tabella \var{fd\_open} al valore minimo,
+corrispondente al file descriptor del socket in ascolto.
+
+Il primo passo (\texttt{\small 30}) nella verifica è incrementare il valore
+dell'indice \var{i} per posizionarsi sul primo valore possibile per un file
+descriptor associato ad un eventuale socket connesso, dopo di che si controlla
+(\texttt{\small 31}) se questo è nella tabella dei socket connessi, chiedendo
+la ripetizione del ciclo in caso contrario. Altrimenti si passa a verificare
+(\texttt{\small 32}) se il file descriptor corrisponde ad uno di quelli
+attivi, e nel caso si esegue (\texttt{\small 33}) una lettura, uscendo con un
+messaggio in caso di errore (\texttt{\small 34--38}).
+
+Se (\texttt{\small 39}) il numero di byte letti \var{nread} è nullo si è in
+presenza del caso di un \textit{end-of-file}, indice che una connessione che
+si è chiusa, che deve essere trattato (\texttt{\small 39--48}) opportunamente.
+Il primo passo è chiudere (\texttt{\small 40}) anche il proprio capo del
+socket e rimuovere (\texttt{\small 41}) il file descriptor dalla tabella di
+quelli aperti, inoltre occorre verificare (\texttt{\small 42}) se il file
+descriptor chiuso è quello con il valore più alto, nel qual caso occorre
+trovare (\texttt{\small 42--46}) il nuovo massimo, altrimenti (\texttt{\small
+ 47}) si può ripetere il ciclo da capo per esaminare (se ne restano)
+ulteriori file descriptor attivi.
+
+Se però è stato chiuso il file descriptor più alto, dato che la scansione dei
+file descriptor attivi viene fatta a partire dal valore più basso, questo
+significa che siamo anche arrivati alla fine della scansione, per questo
+possiamo utilizzare direttamente il valore dell'indice \var{i} con un ciclo
+all'indietro (\texttt{\small 43}) che trova il primo valore per cui la tabella
+presenta un file descriptor aperto, e lo imposta (\texttt{\small 44}) come
+nuovo massimo, per poi tornare (\texttt{\small 44}) al ciclo principale con un
+\code{break}, e rieseguire \func{select}.
+
+Se infine si sono effettivamente letti dei dati dal socket (ultimo caso
+rimasto) si potrà invocare immediatamente (\texttt{\small 49})
+\func{FullWrite} per riscriverli indietro sul socket stesso, avendo cura di
+uscire con un messaggio in caso di errore (\texttt{\small 50--53}). Si noti
+che nel ciclo si esegue una sola lettura, contrariamente a quanto fatto con la
+precedente versione (si riveda il codice di fig.~\ref{fig:TCP_ServEcho_second})
+in cui si continuava a leggere fintanto che non si riceveva un
+\textit{end-of-file}, questo perché usando l'\textit{I/O multiplexing} non si
+vuole essere bloccati in lettura. L'uso di \func{select} ci permette di
+trattare automaticamente anche il caso in cui la \func{read} non è stata in
+grado di leggere tutti i dati presenti sul socket, dato che alla iterazione
+successiva \func{select} ritornerà immediatamente segnalando l'ulteriore
+disponibilità.
+
+Il nostro server comunque soffre di una vulnerabilità per un attacco di tipo
+\itindex{Denial~of~Service~(DoS)} \textit{Denial of Service}. Il problema è
+che in caso di blocco di una qualunque delle funzioni di I/O, non avendo usato
+processi separati, tutto il server si ferma e non risponde più a nessuna
+richiesta. Abbiamo scongiurato questa evenienza per l'I/O in ingresso con
+l'uso di \func{select}, ma non vale altrettanto per l'I/O in uscita. Il
+problema pertanto può sorgere qualora una delle chiamate a \func{write}
+effettuate da \func{FullWrite} si blocchi. Con il funzionamento normale questo
+non accade in quanto il server si limita a scrivere quanto riceve in ingresso,
+ma qualora venga utilizzato un client malevolo che esegua solo scritture e non
+legga mai indietro l'\textsl{eco} del server, si potrebbe giungere alla
+saturazione del buffer di scrittura, ed al conseguente blocco del server su di
+una \func{write}.
+
+Le possibili soluzioni in questo caso sono quelle di ritornare ad eseguire il
+ciclo di risposta alle richieste all'interno di processi separati, utilizzare
+un timeout per le operazioni di scrittura, o eseguire queste ultime in
+modalità non bloccante, concludendo le operazioni qualora non vadano a buon
+fine.
+
+
+
+\subsection{I/O multiplexing con \func{poll}}
+\label{sec:TCP_serv_poll}
+
+Finora abbiamo trattato le problematiche risolubili con l'I/O multiplexing
+impiegando la funzione \func{select}; questo è quello che avviene nella
+maggior parte dei casi, in quanto essa è nata sotto BSD proprio per affrontare
+queste problematiche con i socket. Abbiamo però visto in
+sez.~\ref{sec:file_multiplexing} come la funzione \func{poll} possa costituire
+una alternativa a \func{select}, con alcuni vantaggi.\footnote{non soffrendo
+ delle limitazioni dovute all'uso dei \itindex{file~descriptor~set}
+ \textit{file descriptor set}.}
+
+Ancora una volta in sez.~\ref{sec:file_poll} abbiamo trattato la funzione in
+maniera generica, parlando di file descriptor, ma come per \func{select}
+quando si ha a che fare con dei socket il concetto di essere \textsl{pronti}
+per l'I/O deve essere specificato nei dettagli, per tener conto delle
+condizioni della rete. Inoltre deve essere specificato come viene classificato
+il traffico nella suddivisione fra dati normali e prioritari. In generale
+pertanto:
+\begin{itemize}
+\item i dati inviati su un socket vengono considerati traffico normale,
+ pertanto vengono rilevati alla loro ricezione sull'altro capo da una
+ selezione effettuata con \const{POLLIN} o \const{POLLRDNORM};
+\item i dati urgenti \itindex{out-of-band} \textit{out-of-band} (vedi
+ sez.~\ref{sec:TCP_urgent_data}) su un socket TCP vengono considerati
+ traffico prioritario e vengono rilevati da una condizione \const{POLLIN},
+ \const{POLLPRI} o \const{POLLRDBAND}.
+\item la chiusura di una connessione (cioè la ricezione di un segmento FIN)
+ viene considerato traffico normale, pertanto viene rilevato da una
+ condizione \const{POLLIN} o \const{POLLRDNORM}, ma una conseguente chiamata
+ a \func{read} restituirà 0.
+\item la disponibilità di spazio sul socket per la scrittura di dati viene
+ segnalata con una condizione \const{POLLOUT}.
+\item quando uno dei due capi del socket chiude un suo lato della connessione
+ con \func{shutdown} si riceve una condizione di \const{POLLHUP}.
+\item la presenza di un errore sul socket (sia dovuta ad un segmento RST che a
+ timeout) viene considerata traffico normale, ma viene segnalata anche dalla
+ condizione \const{POLLERR}.
+\item la presenza di una nuova connessione su un socket in ascolto può essere
+ considerata sia traffico normale che prioritario, nel caso di Linux
+ l'implementazione la classifica come normale.
+\end{itemize}
+
+Come esempio dell'uso di \func{poll} proviamo allora a reimplementare il
+server \textit{echo} secondo lo schema di fig.~\ref{fig:TCP_echo_multiplex}
+usando \func{poll} al posto di \func{select}. In questo caso dovremo fare
+qualche modifica, per tenere conto della diversa sintassi delle due funzioni,
+ma la struttura del programma resta sostanzialmente la stessa.
+
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/poll_echod.c}
+ \end{minipage}
+ \normalsize
+ \caption{La sezione principale del codice della nuova versione di server
+ \textit{echo} basati sull'uso della funzione \func{poll}.}
+ \label{fig:TCP_PollEchod}
+\end{figure}
+
+In fig.~\ref{fig:TCP_PollEchod} è riportata la sezione principale della nuova
+versione del server, la versione completa del codice è riportata nel file
+\texttt{poll\_echod.c} dei sorgenti allegati alla guida. Al solito nella
+figura si sono tralasciate la gestione delle opzioni, la creazione del socket
+in ascolto, la cessione dei privilegi e le operazioni necessarie a far
+funzionare il programma come demone, privilegiando la sezione principale del
+programma.