Questo me l'ero dimenticato. Nuovo codice della funzione principale del client
[gapil.git] / tcpsockadv.tex
1  %% tcpsockadv.tex
2 %%
3 %% Copyright (C) 2003 Simone Piccardi.  Permission is granted to
4 %% copy, distribute and/or modify this document under the terms of the GNU Free
5 %% Documentation License, Version 1.1 or any later version published by the
6 %% Free Software Foundation; with the Invariant Sections being "Prefazione",
7 %% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
8 %% license is included in the section entitled "GNU Free Documentation
9 %% License".
10 %%
11 \chapter{Socket TCP avanzati}
12 \label{cha:TCP_advanced}
13
14 Esamineremo in questo capitolo le funzionalità più evolute della gestione dei
15 socket TCP, come l'uso del I/O multiplexing (trattato in
16 \secref{sec:file_multiplexing}) con i socket, l'uso delle opzioni dei socket e
17 la gestione dei dati urgenti e \textit{out-of-band}.
18
19
20
21 \section{Socket I/O multiplexing}
22 \label{sec:TCP_sock_multiplexing}
23
24 Affronteremo in questa sezione l'utilizzo dell'I/O multiplexing, affrontato in
25 \secref{sec:file_multiplexing}, nell'ambito delle applicazioni di rete. Già in
26 \secref{sec:TCP_server_crash} era emerso il problema relativo al client del
27 servizio echo che non era in grado di accorgersi della terminazione precoce
28 del server, essendo bloccato nella lettura dei dati immessi da tastiera.
29
30 Abbiamo visto in \secref{sec:file_multiplexing} quali sono le funzionalità del
31 sistema che ci permettono di tenere sotto controllo più file descriptor in
32 contemporanea; in quella occasione non abbiamo fatto esempi, in quanto quando
33 si tratta con file normali questa tipologia di I/O normalmente non viene
34 usata, è invece un caso tipico delle applicazioni di rete quello di dover
35 gestire varie connessioni da cui possono arrivare dati comuni in maniera
36 asincrona, per cui riprenderemo l'argomento in questa sezione.
37
38
39 \subsection{Il comportamento della funzione \func{select} con i socket.}
40 \label{sec:TCP_sock_select}
41
42 Iniziamo con la prima delle funzioni usate per l'I/O multiplexing,
43 \func{select}; il suo funzionamento è già stato descritto in dettaglio in
44 \secref{sec:file_multiplexing} e non staremo a ripetere quanto detto lì; 
45 sappiamo che la funzione ritorna quando uno o più dei file descriptor messi
46 sotto controllo è pronto per la relativa operazione.
47
48 In quell'occasione non abbiamo però definito cosa si intende per pronto,
49 infatti per dei normali file, o anche per delle pipe, la condizione di essere
50 pronti per la lettura o la scrittura è ovvia; invece lo è molto meno nel caso
51 dei socket, visto che possono intervenire tutte una serie di possibili
52 condizioni di errore dovute alla rete. Occorre allora specificare chiaramente
53 quali sono le condizioni per cui un socket risulta essere ``\textsl{pronto}''
54 quando viene passato come membro di uno dei tre \textit{file descriptor set}
55 usati da \func{select}.
56
57 Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
58 che un socket (che sarà riportato nel primo insieme di file descriptor) è
59 pronto per la lettura sono le seguenti:
60 \begin{itemize*}
61 \item nel buffer di ricezione del socket sono arrivati dei dati in quantità
62   sufficiente a superare il valore di una \textsl{soglia di basso livello} (il
63   cosiddetto \textit{low watermark}). Questo valore è espresso in numero di
64   byte e può essere impostato con l'opzione del socket \const{SO\_RCVLOWAT}
65   (tratteremo le opzioni dei socket in \secref{sec:TCP_sock_options}); il suo
66   valore di default è 1 per i socket TCP e UDP. In questo caso una operazione
67   di lettura avrà successo e leggerà un numero di byte maggiore di zero.
68 \item il lato in lettura della connessione è stato chiuso; si è cioè ricevuto
69   un segmento FIN (si ricordi quanto illustrato in \secref{sec:TCP_conn_term})
70   sulla connessione. In questo caso una operazione di lettura avrà successo,
71   ma non risulteranno presenti dati (in sostanza \func{read} ritornerà con un
72   valore nullo) per indicare la condizione di end-of-file.
73 \item c'è stato un errore sul socket. In questo caso una operazione di lettura
74   non si bloccherà ma restituirà una condizione di errore (ad esempio
75   \func{read} restituirà -1) e imposterà la variabile \var{errno} al relativo
76   valore. Vedremo in \secref{sec:TCP_sock_options} come sia possibile estrarre
77   e cancellare errori pendenti su un socket usando l'opzione
78   \const{SO\_ERROR}.
79 \item quando si sta utilizzando un \textit{listening socket} ed ci sono delle
80   connessioni completate. In questo caso la funzione \func{accept} non si
81   bloccherà.\footnote{in realtà questo non è sempre vero, come accennato in
82     \secref{sec:TCP_conn_early_abort} una connessione può essere abortita
83     dalla ricezione di un segmento RST una volta che è stata completata,
84     allora se questo avviene dopo che \func{select} è ritornata, ma prima
85     della chiamata ad \func{accept}, quest'ultima, in assenza di altre
86     connessioni, potrà bloccarsi.}
87 \end{itemize*}
88
89 Le condizioni che fanno si che la funzione \func{select} ritorni segnalando
90 che un socket (che sarà riportato nel secondo insieme di file descriptor) è
91 pronto per la scrittura sono le seguenti:
92 \begin{itemize*}
93 \item nel buffer di invio è disponibile una quantità di spazio superiore al
94   valore della \textsl{soglia di basso livello} in scrittura ed inoltre o il
95   socket è già connesso o non necessita (ad esempio è UDP) di connessione.  Il
96   valore della soglia è espresso in numero di byte e può essere impostato con
97   l'opzione del socket \const{SO\_SNDLOWAT}; il suo valore di default è 2048
98   per i socket TCP e UDP. In questo caso una operazione di scrittura non si
99   bloccherà e restituirà un valore positivo pari al numero di byte accettati
100   dal livello di trasporto.
101 \item il lato in scrittura della connessione è stato chiuso. In questo caso
102   una operazione di scrittura sul socket genererà il segnale \const{SIGPIPE}.
103 \item c'è stato un errore sul socket. In questo caso una operazione di
104   scrittura non si bloccherà ma restituirà una condizione di errore ed
105   imposterà opportunamente la variabile \var{errno}. Vedremo in
106   \secref{sec:TCP_sock_options} come sia possibile estrarre e cancellare
107   errori pendenti su un socket usando l'opzione \const{SO\_ERROR}.
108 \end{itemize*}
109
110 Infine c'è una sola condizione che fa si che \func{select} ritorni segnalando
111 che un socket (che sarà riportato nel terzo insieme di file descriptor) ha una
112 condizione di eccezione pendente, e cioè la ricezione sul socket di dati
113 \textsl{fuori banda} (o \textit{out-of-band}), una caratteristica specifica
114 dei socket TCP su cui torneremo in \secref{sec:TCP_urgent_data}.
115
116 Si noti come nel caso della lettura \func{select} si applichi anche ad
117 operazioni che non hanno nulla a che fare con l'I/O di dati come il
118 riconoscimento della presenza di connessioni pronte, in modo da consentire
119 anche l'utilizzo di \func{accept} in modalità non bloccante. Si noti infine
120 come in caso di errore un socket venga sempre riportato come pronto sia per la
121 lettura che per la scrittura.
122
123 Lo scopo dei due valori di soglia per i buffer di ricezione e di invio è
124 quello di consentire maggiore flessibilità nell'uso di \func{select} da parte
125 dei programmi, se infatti si sa che una applicazione non è in grado di fare
126 niente fintanto che non può ricevere o inviare una certa quantità di dati, si
127 possono utilizzare questi valori per far si che \func{select} ritorni solo
128 quando c'è la certezza di avere dati a sufficienza.\footnote{questo tipo di
129   controllo è utile di norma solo per la lettura, in quanto in genere le
130   operazioni di scrittura sono già controllate dall'applicazione, che sà
131   sempre quanti dati invia, mentre non è detto possa conoscere la quantità di
132   dati in ricezione; per cui, nella situazione in cui si conosce almeno un
133   valore minimo, per evitare la penalizzazione dovuta alla ripetizione delle
134   operazioni di lettura per accumulare dati sufficienti, si può lasciare al
135   kernel il compito di impostare un minimo al di sotto del quale il file
136   descriptor, pur avendo disponibili dei dati, non viene dato per pronto in
137   lettura.}
138
139
140
141 \subsection{Un esempio di I/O multiplexing}
142 \label{sec:TCP_multiplex_example}
143
144 Abbiamo incontrato la problematica tipica che conduce all'uso dell'I/O
145 multiplexing nella nostra analisi degli errori in
146 \secref{sec:TCP_conn_early_abort}, quando il nostro client non era in grado di
147 rendersi conto di errori sulla connessione essendo impegnato nella attesa di
148 dati in ingresso dallo standard input.
149
150 In questo caso il problema è quello di dover tenere sotto controllo due
151 diversi file descriptor, lo standard input, da cui viene letto il testo che
152 vogliamo inviare al server, e il socket connesso con il server su cui detto
153 testo sarà scritto e dal quale poi si vorrà ricevere la risposta. L'uso
154 dell'I/O multiplexing consente di tenere sotto controllo entrambi, senza
155 restare bloccati.
156
157 Nel nostro caso quello che ci interessa è non essere bloccati in lettura sullo
158 standard input in caso di errori sulla connessione o chiusura della stessa da
159 parte del server. Entrambi questi casi possono essere rilevati usando
160 \func{select}, per quanto detto in \secref{sec:TCP_sock_select}, mettendo
161 sotto osservazione i file descriptor per la condizione di essere pronti in
162 lettura: sia infatti che si ricevano dati, che la connessione sia chiusa
163 regolarmente (con la ricezione di un segmento FIN) che si riceva una
164 condizione di errore (con un segmento RST) il socket connesso sarà pronto in
165 lettura (nell'ultimo caso anche in scrittura, ma questo non è necessario ai
166 nostri scopi).
167
168 \begin{figure}[!htb]
169   \footnotesize \centering
170   \begin{minipage}[c]{15.6cm}
171     \includecodesample{listati/ClientEcho_third.c}
172   \end{minipage} 
173   \normalsize
174   \caption{La sezione nel codice della terza versione della funzione
175     \func{ClientEcho} usata dal client per il servizio \textit{echo}
176     modificata per l'uso di \func{select}.}
177   \label{fig:TCP_ClientEcho_third}
178 \end{figure}
179
180 Riprendiamo allora il codice del client, modificandolo per l'uso di
181 \func{select}. Quello che dobbiamo modificare è la funzione \func{ClientEcho}
182 di \figref{fig:TCP_ClientEcho_second}, dato che tutto il resto, che riguarda
183 le modalità in cui viene stabilita la connessione con il server, resta
184 assolutamente identico. La nostra nuova versione di \func{ClientEcho}, la
185 terza della serie, è riportata in \figref{fig:TCP_ClientEcho_third}.
186
187 In questo caso la funzione comincia (\texttt{\small 8--9}) con la
188 cancellazione del file descriptor set \var{fset} e del valore \var{maxfd} da
189 passare a \func{select} come massimo per il numero dei file descriptor. Per
190 quest'ultimo si usa la macro \code{max} definita nel nostro file
191 \file{macro.h} che raccoglie una collezione di macro di preprocessore di varia
192 utilità.
193
194 La funzione prosegue poi (\texttt{\small 10--41}) con il ciclo principale, che
195 viene ripetuto indefinitamente. Per ogni ciclo si reinizializza
196 (\texttt{\small 11--12}) il file descriptor set, impostando i valori per il
197 file descriptor associato al socket \var{socket} e per lo standard input (il
198 cui valore si recupera con la funzione \func{fileno}). Questo è necessario in
199 quanto la successiva (\texttt{\small 13}) chiamata a \func{select} comporta
200 una modifica dei due bit relativi, che quindi devono essere reimpostati.
201
202 Si noti come la chiamata a \func{select} venga eseguita usando come primo
203 argomento il valore di \var{maxfd}, precedentemente calcolato, passando poi il
204 solo file descriptor set per il controllo dell'attività in lettura, gli altri
205 argomenti sono tutti passati come puntatori nulli non interessando né il
206 controllo delle altre attività, né l'impostazione di un valore di timeout.
207
208 Al ritorno di \func{select} si provvede a controllare quale dei file
209 descriptor presneta attività, si comincia (\texttt{\small 14--24}) con il file
210 descriptor associato allo standard input. In caso di attività (quando cioè
211 \macro{FD_ISSET} ritorna una valore diverso da zero) si esegue (\texttt{\small
212   15}) una \func{fgets} per leggere gli eventuali dati presenti; se non ve ne
213 sono (e la funzione restituisce pertanto un puntatore nullo) si ritorna
214 immediatamente (\texttt{\small 16}) dato che questo significa che si è chiuso
215 lo standard input; altrimenti (\texttt{\small 18--22}) si scrivono i dati sul
216 socket, uscendo immediatamente in caso di errore di scrittura.
217
218 Controllato lo standard input si passa a controllare (\texttt{\small 25--40})
219 il socket connesso, in caso di attività si esegue (\texttt{\small 26}) subito
220 una \func{read} di cui si controlla il valore di ritorno; se questo è negativo
221 (\texttt{\small 27--30}) si è avuto un errore e pertanto si esce
222 immediatamente segnalandolo, se è nullo (\texttt{\small 31--34}) 
223
224
225 \section{Le opzioni dei socket}
226 \label{sec:TCP_sock_options}
227
228 Dato che la maggior parte delle opzioni dei socket sono relative ai socket
229 TCP, ed hanno poi significato analogo quando usate con altri socket, abbiamo
230 preferito trattare l'argomento in generale in questa sezione piuttosto che nel
231 capitolo dedicato alla trattazione generica dei socket.
232
233
234
235 \section{I dati \textit{out-of-band}}
236 \label{sec:TCP_urgent_data}
237
238 Una caratteristica speciale dei socket TCP è quella della presenza dei
239 cosiddetti dati \textit{out-of-band}
240
241
242
243 \subsection{La funzione \func{shutdown}}
244 \label{sec:TCP_shutdown}
245
246 Come spiegato in \secref{sec:TCP_conn_term} il procedimento di chiusura di un
247 socket TCP prevede che da entrambe le parti venga emesso un segmento FIN. È
248 pertanto del tutto normale dal punto di vista del protocollo che uno dei due
249 capi chiuda la connessione, quando l'altro capo la lascia
250 aperta.\footnote{abbiamo incontrato questa situazione nei vari scenari critici
251   di \secref{sec:TCP_echo_critical}.}
252
253 È pertanto possibile avere una situazione in cui un capo della connessione non
254 avendo più nulla da scrivere, possa chiudere il socket, segnalando così
255 l'avvenuta terminazione della trasmissione (l'altro capo riceverà infatti un
256 end-of-file in lettura) mentre dall'altra parte si potrà proseguire la
257 trasmissione dei dati scrivendo sul socket che da quel lato è ancora aperto.
258 Questa è quella situazione in cui si dice che il socket è \textit{half
259   closed}.
260
261 Il problema che si pone è che se la chiusura del socket è effettuata con la
262 funzione \func{close}, come spiegato in \secref{sec:TCP_func_close}, si perde
263 ogni possibilità di poter rileggere quanto l'altro capo può continuare a
264 scrivere. Per poter permettere allora 
265
266
267
268
269 %%% Local Variables: 
270 %%% mode: latex
271 %%% TeX-master: "gapil"
272 %%% End: