Ristrutturazione della sezione sulla programmazione di rete, tentativo di
[gapil.git] / tcpsockadv.tex
diff --git a/tcpsockadv.tex b/tcpsockadv.tex
deleted file mode 100644 (file)
index 991fe04..0000000
+++ /dev/null
@@ -1,861 +0,0 @@
-%% tcpsockadv.tex
-%%
-%% Copyright (C) 2003 Simone Piccardi.  Permission is granted to
-%% copy, distribute and/or modify this document under the terms of the GNU Free
-%% Documentation License, Version 1.1 or any later version published by the
-%% Free Software Foundation; with the Invariant Sections being "Prefazione",
-%% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
-%% license is included in the section entitled "GNU Free Documentation
-%% License".
-%%
-\chapter{Socket TCP avanzati}
-\label{cha:TCP_advanced}
-
-Esamineremo in questo capitolo le funzionalità più evolute della gestione dei
-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 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
-\secref{sec:TCP_server_crash} era emerso il problema relativo al client del
-servizio echo che non era in grado di accorgersi della terminazione precoce
-del server, essendo bloccato nella lettura dei dati immessi da tastiera.
-
-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 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
-\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; invece lo è molto meno nel caso
-dei socket, visto che possono intervenire tutte una serie di possibili
-condizioni di errore dovute alla rete. Occorre allora specificare chiaramente
-quali sono le condizioni per cui un socket risulta essere ``\textsl{pronto}''
-quando viene passato come membro di uno dei tre \textit{file descriptor set}
-usati da \func{select}.
-
-Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
-che un socket (che sarà riportato nel primo insieme di file descriptor) è
-pronto per la lettura sono le seguenti:
-\begin{itemize*}
-\item nel buffer di ricezione del socket sono arrivati dei dati in quantità
-  sufficiente a superare il valore di una \textsl{soglia di basso livello} (il
-  cosiddetto \textit{low watermark}). Questo valore è espresso in numero di
-  byte e può essere impostato con l'opzione del socket \const{SO\_RCVLOWAT}
-  (tratteremo le opzioni dei socket in \secref{sec:TCP_sock_options}); il suo
-  valore di default è 1 per i socket TCP e UDP. In questo caso una operazione
-  di lettura avrà successo e leggerà un numero di byte maggiore di zero.
-\item il lato in lettura della connessione è stato chiuso; si è cioè ricevuto
-  un segmento FIN (si ricordi quanto illustrato in \secref{sec:TCP_conn_term})
-  sulla connessione. In questo caso una operazione di lettura avrà successo,
-  ma non risulteranno presenti dati (in sostanza \func{read} ritornerà con un
-  valore nullo) per indicare la condizione di end-of-file.
-\item c'è stato un errore sul socket. In questo caso una operazione di lettura
-  non si bloccherà ma restituirà una condizione di errore (ad esempio
-  \func{read} restituirà -1) e imposterà la variabile \var{errno} al relativo
-  valore. Vedremo in \secref{sec:TCP_sock_options} come sia possibile estrarre
-  e cancellare errori pendenti su un socket usando l'opzione
-  \const{SO\_ERROR}.
-\item quando si sta utilizzando un \textit{listening socket} ed ci sono delle
-  connessioni completate. In questo caso la funzione \func{accept} non si
-  bloccherà.\footnote{in realtà questo non è sempre vero, come accennato in
-    \secref{sec:TCP_conn_early_abort} una connessione può essere abortita
-    dalla ricezione di un segmento RST una volta che è stata completata,
-    allora se questo avviene dopo che \func{select} è ritornata, ma prima
-    della chiamata ad \func{accept}, quest'ultima, in assenza di altre
-    connessioni, potrà bloccarsi.}
-\end{itemize*}
-
-Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
-che un socket (che sarà riportato nel secondo insieme di file descriptor) è
-pronto per la scrittura sono le seguenti:
-\begin{itemize*}
-\item nel buffer di invio è disponibile una quantità di spazio superiore al
-  valore della \textsl{soglia di basso livello} in scrittura ed inoltre o il
-  socket è già connesso o non necessita (ad esempio è UDP) di connessione.  Il
-  valore della soglia è espresso in numero di byte e può essere impostato con
-  l'opzione del socket \const{SO\_SNDLOWAT}; il suo valore di default è 2048
-  per i socket TCP e UDP. In questo caso una operazione di scrittura non si
-  bloccherà e restituirà un valore positivo pari al numero di byte accettati
-  dal livello di trasporto.
-\item il lato in scrittura della connessione è stato chiuso. In questo caso
-  una operazione di scrittura sul socket genererà il segnale \const{SIGPIPE}.
-\item c'è stato un errore sul socket. In questo caso una operazione di
-  scrittura non si bloccherà ma restituirà una condizione di errore ed
-  imposterà opportunamente la variabile \var{errno}. Vedremo in
-  \secref{sec:TCP_sock_options} come sia possibile estrarre e cancellare
-  errori pendenti su un socket usando l'opzione \const{SO\_ERROR}.
-\end{itemize*}
-
-Infine c'è una sola condizione che fa si che \func{select} ritorni segnalando
-che un socket (che sarà riportato nel terzo insieme di file descriptor) ha una
-condizione di eccezione pendente, e cioè la ricezione sul socket di dati
-\textsl{fuori banda} (o \textit{out-of-band}), una caratteristica specifica
-dei socket TCP su cui torneremo in \secref{sec:TCP_urgent_data}.
-
-Si noti come nel caso della lettura \func{select} si applichi anche ad
-operazioni che non hanno nulla a che fare con l'I/O di dati come il
-riconoscimento della presenza di connessioni pronte, in modo da consentire
-anche l'utilizzo di \func{accept} in modalità non bloccante. Si noti infine
-come in caso di errore un socket venga sempre riportato come pronto sia per la
-lettura che per la scrittura.
-
-Lo scopo dei due valori di soglia per i buffer di ricezione e di invio è
-quello di consentire maggiore flessibilità nell'uso di \func{select} da parte
-dei programmi, se infatti si sa che una applicazione non è in grado di fare
-niente fintanto che non può ricevere o inviare una certa quantità di dati, si
-possono utilizzare questi valori per far si che \func{select} ritorni solo
-quando c'è la certezza di avere dati a sufficienza.\footnote{questo tipo di
-  controllo è utile di norma solo per la lettura, in quanto in genere le
-  operazioni di scrittura sono già controllate dall'applicazione, che sà
-  sempre quanti dati invia, mentre non è detto possa conoscere la quantità di
-  dati in ricezione; per cui, nella situazione in cui si conosce almeno un
-  valore minimo, per evitare la penalizzazione dovuta alla ripetizione delle
-  operazioni di lettura per accumulare dati sufficienti, si può lasciare al
-  kernel il compito di impostare un minimo al di sotto del quale il file
-  descriptor, pur avendo disponibili dei dati, non viene dato per pronto in
-  lettura.}
-
-
-
-\subsection{Un esempio di I/O multiplexing}
-\label{sec:TCP_multiplex_example}
-
-Abbiamo incontrato la problematica tipica che conduce all'uso dell'I/O
-multiplexing nella nostra analisi degli errori in
-\secref{sec:TCP_conn_early_abort}, quando il nostro client non era in grado di
-rendersi conto di errori sulla connessione essendo impegnato nella attesa di
-dati in ingresso dallo standard input.
-
-In questo caso il problema è quello di dover tenere sotto controllo due
-diversi file descriptor, lo standard input, da cui viene letto il testo che
-vogliamo inviare al server, e il socket connesso con il server su cui detto
-testo sarà scritto e dal quale poi si vorrà ricevere la risposta. L'uso
-dell'I/O multiplexing consente di tenere sotto controllo entrambi, senza
-restare bloccati.
-
-Nel nostro caso quello che ci interessa è non essere bloccati in lettura sullo
-standard input in caso di errori sulla connessione o chiusura della stessa da
-parte del server. Entrambi questi casi possono essere rilevati usando
-\func{select}, per quanto detto in \secref{sec:TCP_sock_select}, mettendo
-sotto osservazione i file descriptor per la condizione di essere pronti in
-lettura: sia infatti che si ricevano dati, che la connessione sia chiusa
-regolarmente (con la ricezione di un segmento FIN) che si riceva una
-condizione di errore (con un segmento RST) il socket connesso sarà pronto in
-lettura (nell'ultimo caso anche in scrittura, ma questo non è necessario ai
-nostri scopi).
-
-\begin{figure}[!htb]
-  \footnotesize \centering
-  \begin{minipage}[c]{15.6cm}
-    \includecodesample{listati/ClientEcho_third.c}
-  \end{minipage} 
-  \normalsize
-  \caption{La sezione nel codice della terza versione della funzione
-    \func{ClientEcho} usata dal client per il servizio \textit{echo}
-    modificata per l'uso di \func{select}.}
-  \label{fig:TCP_ClientEcho_third}
-\end{figure}
-
-Riprendiamo allora il codice del client, modificandolo per l'uso di
-\func{select}. Quello che dobbiamo modificare è la funzione \func{ClientEcho}
-di \figref{fig:TCP_ClientEcho_second}, dato che tutto il resto, che riguarda
-le modalità in cui viene stabilita la connessione con il server, resta
-assolutamente identico. La nostra nuova versione di \func{ClientEcho}, la
-terza della serie, è riportata in \figref{fig:TCP_ClientEcho_third}, il codice
-completo si trova nel file \file{TCP\_echo\_third.c} dei sorgenti allegati alla
-guida.
-
-In questo caso la funzione comincia (\texttt{\small 8--9}) con l'azzeramento
-del file descriptor set \var{fset} e l'impostazione del valore \var{maxfd}, da
-passare a \func{select} come massimo per il numero di file descriptor. Per
-determinare quest'ultimo si usa la macro \code{max} definita nel nostro file
-\file{macro.h} che raccoglie una collezione di macro di preprocessore di varia
-utilità.
-
-La funzione prosegue poi (\texttt{\small 10--41}) con il ciclo principale, che
-viene ripetuto indefinitamente. Per ogni ciclo si reinizializza
-(\texttt{\small 11--12}) il file descriptor set, impostando i valori per il
-file descriptor associato al socket \var{socket} e per lo standard input (il
-cui valore si recupera con la funzione \func{fileno}). Questo è necessario in
-quanto la successiva (\texttt{\small 13}) chiamata a \func{select} comporta
-una modifica dei due bit relativi, che quindi devono essere reimpostati
-all'inizio di ogni ciclo.
-
-Si noti come la chiamata a \func{select} venga eseguita usando come primo
-argomento il valore di \var{maxfd}, precedentemente calcolato, e passando poi
-il solo file descriptor set per il controllo dell'attività in lettura, negli
-altri argomenti sono passati tutti puntatori nulli, non interessando né il
-controllo delle altre attività, né l'impostazione di un valore di timeout.
-
-Al ritorno di \func{select} si provvede a controllare quale dei due file
-descriptor presenta attività in lettura, cominciando (\texttt{\small 14--24})
-con il file descriptor associato allo standard input. In caso di attività
-(quando cioè \macro{FD\_ISSET} ritorna una valore diverso da zero) si esegue
-(\texttt{\small 15}) una \func{fgets} per leggere gli eventuali dati presenti;
-se non ve ne sono (e la funzione restituisce pertanto un puntatore nullo) si
-ritorna immediatamente (\texttt{\small 16}) dato che questo significa che si è
-chiuso lo standard input e quindi concluso l'utilizzo del client; altrimenti
-(\texttt{\small 18--22}) si scrivono i dati appena letti sul socket,
-prevedendo una uscita immediata in caso di errore di scrittura.
-
-Controllato lo standard input si passa a controllare (\texttt{\small 25--40})
-il socket connesso, in caso di attività (\texttt{\small 26}) si esegue subito
-una \func{read} di cui si controlla il valore di ritorno; se questo è negativo
-(\texttt{\small 27--30}) si è avuto un errore e pertanto si esce
-immediatamente segnalandolo, se è nullo (\texttt{\small 31--34}) significa che
-il server ha chiuso la connessione, e di nuovo si esce con stampando prima un
-messaggio di avviso, altrimenti (\texttt{\small 35--39}) si effettua la
-terminazione della stringa e la si stampa a sullo standard output (uscendo in
-caso di errore), per ripetere il ciclo da capo.
-
-Con questo meccanismo il programma invece di essere bloccato in lettura sullo
-standard input resta bloccato sulla \func{select}, che ritorna soltanto quando
-viene rilevata attività su uno dei due file descriptor posti sotto controllo.
-Questo di norma avviene solo quando si è scritto qualcosa sullo standard
-input, o quando si riceve dal socket la risposta a quanto si era appena
-scritto. Ma adesso il client diventa capace di accorgersi immediatamente della
-terminazione del server; in tal caso infatti il server chiuderà il socket
-connesso, ed alla ricezione del FIN la funzione \func{select} ritornerà (come
-illustrato in \secref{sec:TCP_sock_select}) segnalando una condizione di end
-of file, per cui il nostro client potrà uscire immediatamente.
-
-Riprendiamo la situazione affrontata in \secref{sec:TCP_server_crash},
-terminando il server durante una connessione, in questo caso quello che
-otterremo, una volta scritta una prima riga ed interrotto il server con un
-\texttt{C-c}, sarà:
-\begin{verbatim}
-[piccardi@gont sources]$ ./echo 192.168.1.1
-Prima riga
-Prima riga
-EOF sul socket
-\end{verbatim}%$
-dove l'ultima riga compare immediatamente dopo aver interrotto il server. Il
-nostro client infatti è in grado di accorgersi immediatamente che il socket
-connesso è stato chiuso ed uscire immediatamente.
-
-Veniamo allora agli altri scenari di terminazione anomala visti in
-\secref{sec:TCP_conn_crash}. Il primo di questi è l'interruzione fisica della
-connessione; in questo caso avremo un comportamento analogo al precedente, in
-cui si scrive una riga e non si riceve risposta dal server e non succede
-niente fino a quando non si riceve un errore di \errcode{EHOSTUNREACH} o
-\errcode{ETIMEDOUT} a seconda dei casi.
-
-La differenza è che stavolta potremo scrivere più righe dopo l'interruzione,
-in quanto il nostro client dopo aver inviato i dati non si bloccherà più nella
-lettura dal socket, ma nella \func{select}; per questo potrà accettare
-ulteriore dati che scriverà di nuovo sul socket, fintanto che c'è spazio sul
-buffer di uscita (ecceduto il quale si bloccherà in scrittura). Si ricordi
-infatti che il client non ha modo di determinare se la connessione è attiva o
-meno (dato che in molte situazioni reali l'inattività può essere temporanea).
-Tra l'altro se si ricollega la rete prima della scadenza del timeout, potremo
-anche verificare come tutto quello che si era scritto viene poi effettivamente
-trasmesso non appena la connessione ridiventa attiva, per cui otterremo
-qualcosa del tipo:
-\begin{verbatim}
-[piccardi@gont sources]$ ./echo 192.168.1.1
-Prima riga
-Prima riga
-Seconda riga dopo l'interruzione
-Terza riga
-Quarta riga
-Seconda riga dopo l'interruzione
-Terza riga
-Quarta riga
-\end{verbatim}
-in cui, una volta riconnessa la rete, tutto quello che abbiamo scritto durante
-il periodo di disconnessione restituito indietro e stampato immediatamente.
-
-Lo stesso comportamento visto in \secref{sec:TCP_server_crash} si riottiene
-nel caso di un crollo completo della macchina su cui sta il server. In questo
-caso di nuovo il client non è in grado di accorgersi di niente dato che si
-suppone che il programma server non venga terminato correttamente, ma si
-blocchi tutto senza la possibilità di avere l'emissione di un segmento FIN che
-segnala la terminazione della connessione. Di nuovo fintanto che la
-connessione non si riattiva )con il riavvio della macchina del server) il
-client non è in grado di fare altro che accettare dell'input e tentare di
-inviarlo. La differenza in questo caso è che non appena la connessione
-ridiventa attiva i dati verranno sì trasmessi, ma essendo state perse tutte le
-informazioni relative alle precedenti connessioni ai tentativi di scrittura
-del client sarà risposto con un segmento RST che provocherà il ritorno di
-\func{select} per la ricezione di un errore di \errcode{ECONNRESET}.
-
-
-\subsection{La funzione \func{shutdown}}
-\label{sec:TCP_shutdown}
-
-Come spiegato in \secref{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 \secref{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 \secref{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
-  \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 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
-\figref{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 \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
-\figref{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 \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}
-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 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 \figref{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
-\figref{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
-\secref{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 \figref{fig:TCP_echo_multiplex}, il
-programma usa una tabella dei socket connessi mantenuta nel vettore
-\var{fd\_open} dimensionato al valore di \macro{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
-\secref{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 \secref{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 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 \secref{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
-\secref{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 \secref{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 trasmessi su un socket vengono considerati traffico normale,
-  pertanto vengono rilevati da una selezione con \const{POLLIN} o
-  \const{POLLRDNORM}.
-\item i dati \textit{out-of-band} 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 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 \figref{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 \figref{fig:TCP_PollEchod} è riportata la sezione principale della nuova
-versione del server, la versione completa del codice è riportata nel file
-\file{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 eventiale 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
-\figref{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 file descriptor set in quanto l'uscita è indipendente dai dati in
-ingresso. 
-
-
-\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}
-
-
-
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "gapil"
-%%% End: