quale processo (o gruppo di processi) riceverà il segnale. Se pertanto si
effettuano le operazioni di I/O in risposta alla ricezione del segnale non ci
sarà più la necessità di restare bloccati in attesa della disponibilità di
-accesso ai file.
+accesso ai file; per questo motivo Stevens chiama questa modalità
+\textit{signal driven I/O}.
In questo modo si può evitare l'uso delle funzioni \func{poll} o \func{select}
che, quando vengono usate con un numero molto grande di file descriptor, non
\include{network}
\include{socket}
\include{tcpsock}
-\include{tcpsockadv}
+\include{othersock}
+\include{sockctrl}
+\include{sockadv}
\appendix
\part{Appendici}
\label{part:appendici}
un'applicazione usa UDP essa scrive un pacchetto di dati (il cosiddetto
\textit{datagram} che da il nome al protocollo) su un socket\index{socket}, al
pacchetto viene aggiunto un header molto semplice (per una descrizione più
-accurata vedi \secref{sec:xxx_udp}), e poi viene passato al livello superiore
-(IPv4 o IPv6 che sia) che lo spedisce verso la destinazione. Dato che né IPv4
-né IPv6 garantiscono l'affidabilità niente assicura che il pacchetto arrivi a
-destinazione, né che più pacchetti arrivino nello stesso ordine in cui sono
-stati spediti.
+accurata vedi \secref{sec:udp_protocol}), e poi viene passato al livello
+superiore (IPv4 o IPv6 che sia) che lo spedisce verso la destinazione. Dato
+che né IPv4 né IPv6 garantiscono l'affidabilità niente assicura che il
+pacchetto arrivi a destinazione, né che più pacchetti arrivino nello stesso
+ordine in cui sono stati spediti.
Pertanto il problema principale che si affronta quando si usa UDP è la
mancanza di affidabilità, se si vuole essere sicuri che i pacchetti arrivino a
--- /dev/null
+%% othersock.tex
+%%
+%% Copyright (C) 2004 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{Gli altri socket più comuni}
+\label{cha:other_socket}
+
+Dopo aver trattato in \capref{cha:TCP_socket} i socket TCP, che costituiscono
+l'esempio più comune dell'interfaccia dei socket, esamineremo in questo
+capitolo gli altri tipi di socket,
+
+
+\section{I socket UDP}
+\label{sec:UDP_socket}
+
+Dopo i socket TCP i socket più utilizzati sono i socket UDP.
+
+
+\section{I socket \textit{Unix domain}}
+\label{sec:UDP_socket}
+
+Benché i socket Unix domain non siano strattamente attinenti alla rete, in
+quanto definiscono una interfaccia di comunicazione locale alla singola
+macchina, li tratteremo comunque in questa sezione in quanto la loro
+interfaccia è comunque basata sulla più generale interfaccia dei socket.
+
+
+
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End:
--- /dev/null
+%% sockadv.tex
+%%
+%% Copyright (C) 2004 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 avanzati}
+\label{cha:advanced_socket}
+
+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 TCP avanzati}
+\label{sec:TCP_advanced_socket}
+
+Trattereno in questa sezione alcune delle funzionalità più avanzate relative
+ai socket TCP. Da fare
+
+
+
+\subsection{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} ...
+
+
+\section{Socket UDP avanzati}
+\label{sec:UDP_advanced_socket}
+
+Trattereno in questa sezione alcune delle funzionalità più avanzate relative
+ai socket UDP. Da fare
+
+
+
+
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% TeX-master: "gapil"
+%%% End:
--- /dev/null
+%% sockctrl.tex
+%%
+%% Copyright (C) 2004 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{La gestione dei socket}
+\label{cha:sock_generic_management}
+
+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{La gestione degli indirizzi}
+\label{sec:sock_addresses}
+
+Effettueremo in questa sezione una trattazione completa delle funzioni
+utilizzate per la gestione degli indirizzi dei socket.
+
+
+
+
+\section{Le opzioni dei socket}
+\label{sec:TCP_sock_options}
+
+Finora abbiamo trattato i socket nel loro comportamento più comune, è però
+possibile attivare alcune modalità diverse di funzionamento degli stessi
+
+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.
+
+
+
+
+
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End:
%% license is included in the section entitled "GNU Free Documentation
%% License".
%%
-\chapter{Socket TCP elementari}
+\chapter{I socket TCP}
\label{cha:TCP_socket}
In questo capitolo iniziamo ad approfondire la conoscenza dei socket TCP,
iniziando con una descrizione delle principali caratteristiche del
funzionamento di una connessione TCP. Tratteremo poi le varie funzioni che
servono alla creazione di una connessione fra un server elementare ed il suo
-client, fornendo poi alcuni esempi di applicazione elementare.
+client, fornendo poi alcuni esempi di applicazione elementare, e finiremo
+prendendo in esame l'uso dell'I/O multiplexing.
\secref{sec:TCP_sock_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
+\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. Si applicano comunque anche a questo server le considerazioni finali
+di \secref{sec:TCP_serv_select}.
+++ /dev/null
-%% 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: