Messi alcuni riferimenti giusti all'urgent data e scritta la versione di
[gapil.git] / tcpsockadv.tex
index 24c45d2cbf9d1aa707fec08f248fbb4e5703530e..44986525fc3141b95422a22548adb4ede34b939a 100644 (file)
 \label{cha:TCP_advanced}
 
 Esamineremo in questo capitolo le funzionalità più evolute della gestione dei
 \label{cha:TCP_advanced}
 
 Esamineremo in questo capitolo le funzionalità più evolute della gestione dei
-socket TCP. 
+socket TCP, come l'uso del I/O multiplexing (trattato in
+\secref{sec:file_multiplexing}) con i socket, l'uso delle opzioni dei socket e
+la gestione dei dati urgenti e \textit{out-of-band}.
 
 
 
 
 
 
-\section{Socket multiplexing}
+\section{Socket I/O multiplexing}
 \label{sec:TCP_sock_multiplexing}
 
 Affronteremo in questa sezione l'utilizzo dell'I/O multiplexing, affrontato in
 \secref{sec:file_multiplexing}, nell'ambito delle applicazioni di rete. Già in
 \label{sec:TCP_sock_multiplexing}
 
 Affronteremo in questa sezione l'utilizzo dell'I/O multiplexing, affrontato in
 \secref{sec:file_multiplexing}, nell'ambito delle applicazioni di rete. Già in
-\ref{sec:TCP_server_crash} era emerso il problema relativo al client del
+\secref{sec:TCP_server_crash} era emerso il problema relativo al client del
 servizio echo che non era in grado di accorgersi della terminazione precoce
 servizio echo che non era in grado di accorgersi della terminazione precoce
-del server essendo bloccato nella lettura dei dati immessi da tastiera.
+del server, essendo bloccato nella lettura dei dati immessi da tastiera.
 
 Abbiamo visto in \secref{sec:file_multiplexing} quali sono le funzionalità del
 sistema che ci permettono di tenere sotto controllo più file descriptor in
 contemporanea; in quella occasione non abbiamo fatto esempi, in quanto quando
 
 Abbiamo visto in \secref{sec:file_multiplexing} quali sono le funzionalità del
 sistema che ci permettono di tenere sotto controllo più file descriptor in
 contemporanea; in quella occasione non abbiamo fatto esempi, in quanto quando
-si tratta con file normali questa tipologia di I/O non viene usata, è invece
-un caso tipico delle applicazioni di rete quello di dover gestire varie
-connessioni da cui possono arrivare dati comuni in maniera asincrona, per cui
-riprenderemo l'argomento in questa sezione.
-
+si tratta con file normali questa tipologia di I/O normalmente non viene
+usata, è invece un caso tipico delle applicazioni di rete quello di dover
+gestire varie connessioni da cui possono arrivare dati comuni in maniera
+asincrona, per cui riprenderemo l'argomento in questa sezione.
 
 
 \subsection{Il comportamento della funzione \func{select} con i socket.}
 \label{sec:TCP_sock_select}
 
 Iniziamo con la prima delle funzioni usate per l'I/O multiplexing,
 
 
 \subsection{Il comportamento della funzione \func{select} con i socket.}
 \label{sec:TCP_sock_select}
 
 Iniziamo con la prima delle funzioni usate per l'I/O multiplexing,
-\func{select}, il suo funzionamento è già stato descritto in dettaglio in
+\func{select}; il suo funzionamento è già stato descritto in dettaglio in
 \secref{sec:file_multiplexing} e non staremo a ripetere quanto detto lì; 
 sappiamo che la funzione ritorna quando uno o più dei file descriptor messi
 sotto controllo è pronto per la relativa operazione.
 
 In quell'occasione non abbiamo però definito cosa si intende per pronto,
 infatti per dei normali file, o anche per delle pipe, la condizione di essere
 \secref{sec:file_multiplexing} e non staremo a ripetere quanto detto lì; 
 sappiamo che la funzione ritorna quando uno o più dei file descriptor messi
 sotto controllo è pronto per la relativa operazione.
 
 In quell'occasione non abbiamo però definito cosa si intende per pronto,
 infatti per dei normali file, o anche per delle pipe, la condizione di essere
-pronti per la lettura o la scrittura è ovvia, lo è un po' meno di meno nel
-caso dei socket, visto che intervengono tutte le possibili condizioni dovute
-alla rete. Occorre allora specificare quali sono le condizioni in cui un
-socket risulta \textsl{pronto} quando viene passato come membro di uno dei tre
-\textit{file descriptor set} usati da \func{select}.
+pronti per la lettura o la scrittura è ovvia; invece lo è molto meno nel caso
+dei socket, visto che possono intervenire tutte una serie di possibili
+condizioni di errore dovute alla rete. Occorre allora specificare chiaramente
+quali sono le condizioni per cui un socket risulta essere ``\textsl{pronto}''
+quando viene passato come membro di uno dei tre \textit{file descriptor set}
+usati da \func{select}.
 
 Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
 che un socket (che sarà riportato nel primo insieme di file descriptor) è
 
 Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
 che un socket (che sarà riportato nel primo insieme di file descriptor) è
@@ -80,8 +82,8 @@ pronto per la lettura sono le seguenti:
     \secref{sec:TCP_conn_early_abort} una connessione può essere abortita
     dalla ricezione di un segmento RST una volta che è stata completata,
     allora se questo avviene dopo che \func{select} è ritornata, ma prima
     \secref{sec:TCP_conn_early_abort} una connessione può essere abortita
     dalla ricezione di un segmento RST una volta che è stata completata,
     allora se questo avviene dopo che \func{select} è ritornata, ma prima
-    della chiamata ad \func{accept} quest'ultima, in assenza di altre
-    connessiioni, potrà bloccarsi.}
+    della chiamata ad \func{accept}, quest'ultima, in assenza di altre
+    connessioni, potrà bloccarsi.}
 \end{itemize*}
 
 Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
 \end{itemize*}
 
 Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
@@ -109,14 +111,14 @@ Infine c'
 che un socket (che sarà riportato nel terzo insieme di file descriptor) ha una
 condizione di eccezione pendente, e cioè la ricezione sul socket di dati
 \textsl{fuori banda} (o \textit{out-of-band}), una caratteristica specifica
 che un socket (che sarà riportato nel terzo insieme di file descriptor) ha una
 condizione di eccezione pendente, e cioè la ricezione sul socket di dati
 \textsl{fuori banda} (o \textit{out-of-band}), una caratteristica specifica
-dei socket TCP su cui torneremo in \secref{sec:TCP_outofband}.
+dei socket TCP su cui torneremo in \secref{sec:TCP_urgent_data}.
 
 Si noti come nel caso della lettura \func{select} si applichi anche ad
 
 Si noti come nel caso della lettura \func{select} si applichi anche ad
-operazioni che non hanno nulla a che fare con l'I/O come il riconoscimento
-della presenza di connessioni pronte, in modo da consentire l'utilizzo di
-\func{accept} in modalità non bloccante. Si noti infine come in caso di errore
-un socket venga sempre riportato come pronto sia per la lettura che per la
-scrittura.
+operazioni che non hanno nulla a che fare con l'I/O di dati come il
+riconoscimento della presenza di connessioni pronte, in modo da consentire
+anche l'utilizzo di \func{accept} in modalità non bloccante. Si noti infine
+come in caso di errore un socket venga sempre riportato come pronto sia per la
+lettura che per la scrittura.
 
 Lo scopo dei due valori di soglia per i buffer di ricezione e di invio è
 quello di consentire maggiore flessibilità nell'uso di \func{select} da parte
 
 Lo scopo dei due valori di soglia per i buffer di ricezione e di invio è
 quello di consentire maggiore flessibilità nell'uso di \func{select} da parte
@@ -129,11 +131,95 @@ quando c'
   sempre quanti dati invia, mentre non è detto possa conoscere la quantità di
   dati in ricezione; per cui, nella situazione in cui si conosce almeno un
   valore minimo, per evitare la penalizzazione dovuta alla ripetizione delle
   sempre quanti dati invia, mentre non è detto possa conoscere la quantità di
   dati in ricezione; per cui, nella situazione in cui si conosce almeno un
   valore minimo, per evitare la penalizzazione dovuta alla ripetizione delle
-  operazioni di lettura quando per accumulare dati sufficienti, si può
-  lasciare al kernel il compito di impostare un minimo al di sotto del quale
-  il file descriptor, pur avendo disponibili dei dati, non viene letto.}
-
-
+  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}.
+
+In questo caso la funzione comincia (\texttt{\small 8--9}) con la
+cancellazione del file descriptor set \var{fset} e del valore \var{maxfd} da
+passare a \func{select} come massimo per il numero dei file descriptor. Per
+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.
+
+Si noti come la chiamata a \func{select} venga eseguita usando come primo
+argomento il valore di \var{maxfd}, precedentemente calcolato, passando poi il
+solo file descriptor set per il controllo dell'attività in lettura, gli altri
+argomenti sono tutti passati come 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 file
+descriptor presneta attività, si comincia (\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; altrimenti (\texttt{\small 18--22}) si scrivono i dati sul
+socket, uscendo immediatamente 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à si esegue (\texttt{\small 26}) 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}) 
 
 
 \section{Le opzioni dei socket}
 
 
 \section{Le opzioni dei socket}
@@ -141,13 +227,13 @@ quando c'
 
 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
 
 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.
+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}}
 
 
 
 \section{I dati \textit{out-of-band}}
-\label{sec:TCP_outofband}
+\label{sec:TCP_urgent_data}
 
 Una caratteristica speciale dei socket TCP è quella della presenza dei
 cosiddetti dati \textit{out-of-band}
 
 Una caratteristica speciale dei socket TCP è quella della presenza dei
 cosiddetti dati \textit{out-of-band}