+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \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 \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 realizzazione 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]{\codesamplewidth}
+ \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 realizzare
+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 \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 \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_close}, 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
+\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
+\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 \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 \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 la
+ realizzazione dello \textit{stack TCP} la classifica come normale.
+\end{itemize}
+
+Come esempio dell'uso di \func{poll} proviamo allora a riscrivere 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]{\codesamplewidth}
+ \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.
+
+Come per il precedente server basato su \func{select} il primo passo
+(\texttt{\small 2--8}) è quello di inizializzare le variabili necessarie. Dato
+che in questo caso dovremo usare un vettore di strutture occorre anzitutto
+(\texttt{\small 2}) allocare la memoria necessaria utilizzando il numero
+massimo \var{n} di socket osservabili, che viene impostato attraverso
+l'opzione \texttt{-n} ed ha un valore di default di 256.
+
+Dopo di che si preimposta (\texttt{\small 3}) il valore \var{max\_fd} del file
+descriptor aperto con valore più alto a quello del socket in ascolto (al
+momento l'unico), e si provvede (\texttt{\small 4--7}) ad inizializzare le
+strutture, disabilitando (\texttt{\small 5}) l'osservazione con un valore
+negativo del campo \var{fd} ma predisponendo (\texttt{\small 6}) il campo
+\var{events} per l'osservazione dei dati normali con \const{POLLRDNORM}.
+Infine (\texttt{\small 8}) si attiva l'osservazione del socket in ascolto
+inizializzando la corrispondente struttura. Questo metodo comporta, in
+modalità interattiva, lo spreco di tre strutture (quelle relative a standard
+input, output ed error) che non vengono mai utilizzate in quanto la prima è
+sempre quella relativa al socket in ascolto.
+
+Una volta completata l'inizializzazione tutto il lavoro viene svolto
+all'interno del ciclo principale \texttt{\small 10--55}) che ha una struttura
+sostanzialmente identica a quello usato per il precedente esempio basato su
+\func{select}. La prima istruzione (\texttt{\small 11--12}) è quella di
+eseguire \func{poll} all'interno di un ciclo che la ripete qualora venisse
+interrotta da un segnale, da cui si esce soltanto quando la funzione ritorna,
+restituendo nella variabile \var{n} il numero di file descriptor trovati
+attivi. Qualora invece si sia ottenuto un errore si procede (\texttt{\small
+ 13--16}) alla terminazione immediata del processo provvedendo a stampare una
+descrizione dello stesso.
+
+Una volta ottenuta dell'attività su un file descriptor si hanno di nuovo due
+possibilità. La prima possibilità è che ci sia attività sul socket in ascolto,
+indice di una nuova connessione, nel qual caso si controlla (\texttt{\small
+ 17}) se il campo \var{revents} della relativa struttura è attivo; se è così
+si provvede (\texttt{\small 18}) a decrementare la variabile \var{n} (che
+assume il significato di numero di file descriptor attivi rimasti da
+controllare) per poi (\texttt{\small 19--23}) effettuare la chiamata ad
+\func{accept}, terminando il processo in caso di errore. Se la chiamata ad
+\func{accept} ha successo si procede attivando (\texttt{\small 24}) la
+struttura relativa al nuovo file descriptor da essa ottenuto, modificando
+(\texttt{\small 24}) infine quando necessario il valore massimo dei file
+descriptor aperti mantenuto in \var{max\_fd}.
+
+La seconda possibilità è che vi sia dell'attività su uno dei socket aperti in
+precedenza, nel qual caso si inizializza (\texttt{\small 27}) l'indice \var{i}
+del vettore delle strutture \struct{pollfd} al valore del socket in ascolto,
+dato che gli ulteriori socket aperti avranno comunque un valore superiore. Il
+ciclo (\texttt{\small 28--54}) prosegue fintanto che il numero di file
+descriptor attivi, mantenuto nella variabile \var{n}, è diverso da zero. Se
+pertanto ci sono ancora socket attivi da individuare si comincia con
+l'incrementare (\texttt{\small 30}) l'indice e controllare (\texttt{\small
+ 31}) se corrisponde ad un file descriptor in uso analizzando il valore del
+campo \var{fd} della relativa struttura e chiudendo immediatamente il ciclo
+qualora non lo sia. Se invece il file descriptor è in uso si verifica
+(\texttt{\small 31}) se c'è stata attività controllando il campo
+\var{revents}.
+
+Di nuovo se non si verifica la presenza di attività il ciclo si chiude subito,
+altrimenti si provvederà (\texttt{\small 32}) a decrementare il numero \var{n}
+di file descriptor attivi da controllare e ad eseguire (\texttt{\small 33}) la
+lettura, ed in caso di errore (\texttt{\small 34--37}) al solito lo si
+notificherà uscendo immediatamente. Qualora invece si ottenga una condizione
+di end-of-file (\texttt{\small 38--47}) si provvederà a chiudere
+(\texttt{\small 39}) anche il nostro capo del socket e a marcarlo
+(\texttt{\small 40}) nella struttura ad esso associata come inutilizzato.
+Infine dovrà essere ricalcolato (\texttt{\small 41--45}) un eventuale nuovo
+valore di \var{max\_fd}. L'ultimo passo è (\texttt{\small 46}) chiudere il
+ciclo in quanto in questo caso non c'è più niente da riscrivere all'indietro
+sul socket.
+
+Se invece si sono letti dei dati si provvede (\texttt{\small 48}) ad
+effettuarne la riscrittura all'indietro, con il solito controllo ed eventuale
+uscita e notifica in caso si errore (\texttt{\small 49--52}).
+
+Come si può notare la logica del programma è identica a quella vista in
+fig.~\ref{fig:TCP_SelectEchod} per l'analogo server basato su \func{select};
+la sola differenza significativa è che in questo caso non c'è bisogno di
+rigenerare i \textit{file descriptor set} in quanto l'uscita è indipendente
+dai dati in ingresso. Si applicano comunque anche a questo server le
+considerazioni finali di sez.~\ref{sec:TCP_serv_select}.
+
+
+
+\subsection{I/O multiplexing con \textit{epoll}}
+\label{sec:TCP_serv_epoll}
+
+Da fare.
+
+% TODO fare esempio con epoll
+
+
+
+% LocalWords: socket TCP client dell'I multiplexing stream three way handshake
+% LocalWords: header stack kernel SYN ACK URG syncronize sez bind listen fig
+% LocalWords: accept connect active acknowledge l'acknowledge nell'header MSS
+% LocalWords: sequence number l'acknowledgement dell'header options l'header
+% LocalWords: option MMS segment size MAXSEG window advertised Mbit sec nell'
+% LocalWords: timestamp RFC long fat close of l'end l'ACK half shutdown CLOSED
+% LocalWords: netstat SENT ESTABLISHED WAIT IPv Ethernet piggybacking UDP MSL
+% LocalWords: l'overhead Stevens Lifetime router hop limit TTL to live RST SSH
+% LocalWords: routing dell'MSL l'IP multitasking well known port ephemeral BSD
+% LocalWords: ports dall' IANA Assigned Authority like glibc netinet IPPORT AF
+% LocalWords: RESERVED USERRESERVED rsh rlogin pair socketpair Local Address
+% LocalWords: Foreing DNS caching INADDR ANY multihoming loopback ssh fuser ip
+% LocalWords: lsof SOCK sys int sockfd const struct sockaddr serv addr socklen
+% LocalWords: addrlen errno EBADF descriptor EINVAL ENOTSOCK EACCES EADDRINUSE
+% LocalWords: EADDRNOTAVAIL EFAULT ENOTDIR ENOENT ENOMEM ELOOP ENOSR EROFS RPC
+% LocalWords: portmapper htonl tab endianness BROADCAST broadcast any extern fd
+% LocalWords: ADRR INIT DGRAM SEQPACKET servaddr ECONNREFUSED ETIMEDOUT EAGAIN
+% LocalWords: ENETUNREACH EINPROGRESS EALREADY EAFNOSUPPORT EPERM EISCONN proc
+% LocalWords: sysctl filesystem syn retries reset ICMP backlog EOPNOTSUPP RECV
+% LocalWords: connection queue dell'ACK flood spoofing syncookies SOMAXCONN CR
+% LocalWords: RDM EWOULDBLOCK firewall ENOBUFS EINTR EMFILE ECONNABORTED NULL
+% LocalWords: ESOCKTNOSUPPORT EPROTONOSUPPORT ERESTARTSYS connected listening
+% LocalWords: DECnet read write NONBLOCK fcntl getsockname getpeername name ps
+% LocalWords: namelen namlen ENOTCONN exec inetd POSIX daytime FullRead count
+% LocalWords: BUF FullWrite system call INET perror htons inet pton ctime FTP
+% LocalWords: fputs carriage return line feed superdemone daytimed sleep fork
+% LocalWords: daemon cunc logging list conn sock exit snprintf ntop ntohs echo
+% LocalWords: crash superserver L'RFC first ClientEcho stdin stdout fgets main
+% LocalWords: MAXLINE initd echod ServEcho setgid short nogroup nobody setuid
+% LocalWords: demonize PrintErr syslog wrapper log error root RTT EOF ctrl ack
+% LocalWords: while SIGCHLD Signal RESTART sigaction SignalRestart SigHand win
+% LocalWords: flags select recvfrom debug second compat waiting Nsec ENETDOWN
+% LocalWords: EPROTO ENOPROTOOPT EHOSTDOWN ENONET EHOSTUNREACH LINGER tcpdump
+% LocalWords: ECONNRESET advertising PSH SIGTERM strace SIGPIPE gets tcp ARP
+% LocalWords: cache anarres destination unreachable l'I low watermark RCVLOWAT
+% LocalWords: SNDLOWAT third fset maxfd fileno ISSET closed how SHUT RD WR eof
+% LocalWords: RDWR fifo Trip ping fourth CLR sull'I SETSIZE nread break Denial
+% LocalWords: Service poll POLLIN POLLRDNORM POLLPRI POLLRDBAND POLLOUT events
+% LocalWords: POLLHUP POLLERR revents pollfd Di scaling SYNCNT DoS