Corretto uso del file nel programma, inserite spiegazioni
[gapil.git] / tcpsockadv.tex
index 24c45d2cbf9d1aa707fec08f248fbb4e5703530e..af3348945068b2df47b195bb85105f81782a4e8f 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,10 +131,112 @@ 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 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.
 
 
 
 
 
 
@@ -141,13 +245,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}