Altra roba che mi ero dimenticato ieri
[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 l'azzeramento
188 del file descriptor set \var{fset} e l'impostazione del valore \var{maxfd}, da
189 passare a \func{select} come massimo per il numero di file descriptor. Per
190 determinare 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 all'inizio di ogni ciclo.
202
203 Si noti come la chiamata a \func{select} venga eseguita usando come primo
204 argomento il valore di \var{maxfd}, precedentemente calcolato, e passando poi
205 il solo file descriptor set per il controllo dell'attività in lettura, negli
206 altri argomenti sono passati tutti puntatori nulli, non interessando né il
207 controllo delle altre attività, né l'impostazione di un valore di timeout.
208
209 Al ritorno di \func{select} si provvede a controllare quale dei due file
210 descriptor presenta attività in lettura, cominciando (\texttt{\small 14--24})
211 con il file descriptor associato allo standard input. In caso di attività
212 (quando cioè \macro{FD\_ISSET} ritorna una valore diverso da zero) si esegue
213 (\texttt{\small 15}) una \func{fgets} per leggere gli eventuali dati presenti;
214 se non ve ne sono (e la funzione restituisce pertanto un puntatore nullo) si
215 ritorna immediatamente (\texttt{\small 16}) dato che questo significa che si è
216 chiuso lo standard input e quindi concluso l'utilizzo del client; altrimenti
217 (\texttt{\small 18--22}) si scrivono i dati appena letti sul socket,
218 prevedendo una uscita immediata in caso di errore di scrittura.
219
220 Controllato lo standard input si passa a controllare (\texttt{\small 25--40})
221 il socket connesso, in caso di attività (\texttt{\small 26}) si esegue subito
222 una \func{read} di cui si controlla il valore di ritorno; se questo è negativo
223 (\texttt{\small 27--30}) si è avuto un errore e pertanto si esce
224 immediatamente segnalandolo, se è nullo (\texttt{\small 31--34}) significa che
225 il server ha chiuso la connessione, e di nuovo si esce con stampando prima un
226 messaggio di avviso, altrimenti (\texttt{\small 35--39}) si effettua la
227 terminazione della stringa e la si stampa a sullo standard output (uscendo in
228 caso di errore), per ripetere il ciclo da capo.
229
230 Con questo meccanismo il programma invece di essere bloccato in lettura sullo
231 standard input resta bloccato sulla \func{select}, che ritorna soltanto quando
232 viene rilevata attività su uno dei due file descriptor posti sotto controllo.
233 Questo di norma avviene solo quando si è scritto qualcosa sullo standard
234 input, o quando si riceve dal socket la risposta a quanto si era appena
235 scritto. Ma adesso il client diventa capace di accorgersi immediatamente della
236 terminazione del server; in tal caso infatti il server chiuderà il socket
237 connesso, ed alla ricezione del FIN la funzione \func{select} ritornerà (come
238 illustrato in \secref{sec:TCP_sock_select}) segnalando una condizione di end
239 of file, per cui il nostro client potrà uscire immediatamente.
240
241 Riprendiamo la situazione affrontata in \secref{sec:TCP_server_crash},
242 terminando il server durante una connessione, in questo caso quello che
243 otterremo, una volta scritta una prima riga ed interrotto il server con un
244 \texttt{C-c}, sarà:
245 \begin{verbatim}
246 [piccardi@gont sources]$ ./echo 192.168.1.1
247 Prima riga
248 Prima riga
249 EOF sul socket
250 \end{verbatim}%$
251 dove l'ultima riga compare immediatamente dopo aver interrotto il server. Il
252 nostro client infatti è in grado di accorgersi immediatamente che il socket
253 connesso è stato chiuso ed uscire immediatamente.
254
255 Veniamo allora agli altri scenari di terminazione anomala visti in
256 \secref{sec:TCP_conn_crash}. Il primo di questi è l'interruzione fisica della
257 connessione; in questo caso avremo un comportamento analogo al precedente, in
258 cui si scrive una riga e non si riceve risposta dal server e non succede
259 niente fino a quando non si riceve un errore di \errcode{EHOSTUNREACH} o
260 \errcode{ETIMEDOUT} a seconda dei casi.
261
262 La differenza è che stavolta potremo scrivere più righe dopo l'interruzione,
263 in quanto il nostro client dopo aver inviato i dati non si bloccherà più nella
264 lettura dal socket, ma nella \func{select}; per questo potrà accettare
265 ulteriore dati che scriverà di nuovo sul socket, fintanto che c'è spazio sul
266 buffer di uscita (ecceduto il quale si bloccherà in scrittura). Si ricordi
267 infatti che il client non ha modo di determinare se la connessione è attiva o
268 meno (dato che in molte situazioni reali l'inattività può essere temporanea).
269 Tra l'altro se si ricollega la rete prima della scadenza del timeout, potremo
270 anche verificare come tutto quello che si era scritto viene poi effettivamente
271 trasmesso non appena la connessione ridiventa attiva, per cui otterremo
272 qualcosa del tipo:
273 \begin{verbatim}
274 [piccardi@gont sources]$ ./echo 192.168.1.1
275 Prima riga
276 Prima riga
277 Seconda riga dopo l'interruzione
278 Terza riga
279 Quarta riga
280 Seconda riga dopo l'interruzione
281 Terza riga
282 Quarta riga
283 \end{verbatim}
284 in cui, una volta riconnessa la rete, tutto quello che abbiamo scritto durante
285 il periodo di disconnessione restituito indietro e stampato immediatamente.
286
287 Lo stesso comportamento visto in \secref{sec:TCP_server_crash} si riottiene
288 nel caso di un crollo completo della macchina su cui sta il server. In questo
289 caso di nuovo il client non è in grado di accorgersi di niente dato che si
290 suppone che il programma server non venga terminato correttamente, ma si
291 blocchi tutto senza la possibilità di avere l'emissione di un segmento FIN che
292 segnala la terminazione della connessione. Di nuovo fintanto che la
293 connessione non si riattiva )con il riavvio della macchina del server) il
294 client non è in grado di fare altro che accettare dell'input e tentare di
295 inviarlo. La differenza in questo caso è che non appena la connessione
296 ridiventa attiva i dati verranno sì trasmessi, ma essendo state perse tutte le
297 informazioni relative alle precedenti connessioni ai tentativi di scrittura
298 del client sarà risposto con un segmento RST che provocherà il ritorno di
299 \func{select} per la ricezione di un errore di \errcode{ECONNRESET}.
300
301
302
303
304 \subsection{La funzione \func{shutdown}}
305 \label{sec:TCP_shutdown}
306
307 Come spiegato in \secref{sec:TCP_conn_term} il procedimento di chiusura di un
308 socket TCP prevede che da entrambe le parti venga emesso un segmento FIN. È
309 pertanto del tutto normale dal punto di vista del protocollo che uno dei due
310 capi chiuda la connessione, quando l'altro capo la lascia
311 aperta.\footnote{abbiamo incontrato questa situazione nei vari scenari critici
312   di \secref{sec:TCP_echo_critical}.}
313
314 È pertanto possibile avere una situazione in cui un capo della connessione non
315 avendo più nulla da scrivere, possa chiudere il socket, segnalando così
316 l'avvenuta terminazione della trasmissione (l'altro capo riceverà infatti un
317 end-of-file in lettura) mentre dall'altra parte si potrà proseguire la
318 trasmissione dei dati scrivendo sul socket che da quel lato è ancora aperto.
319 Questa è quella situazione in cui si dice che il socket è \textit{half
320   closed}.
321
322 Il problema che si pone è che se la chiusura del socket è effettuata con la
323 funzione \func{close}, come spiegato in \secref{sec:TCP_func_close}, si perde
324 ogni possibilità di poter rileggere quanto l'altro capo può continuare a
325 scrivere. Per poter permettere allora 
326
327
328
329 \section{Le opzioni dei socket}
330 \label{sec:TCP_sock_options}
331
332 Dato che la maggior parte delle opzioni dei socket sono relative ai socket
333 TCP, ed hanno poi significato analogo quando usate con altri socket, abbiamo
334 preferito trattare l'argomento in generale in questa sezione piuttosto che nel
335 capitolo dedicato alla trattazione generica dei socket.
336
337
338
339 \section{I dati \textit{out-of-band}}
340 \label{sec:TCP_urgent_data}
341
342 Una caratteristica speciale dei socket TCP è quella della presenza dei
343 cosiddetti dati \textit{out-of-band}
344
345
346
347
348 %%% Local Variables: 
349 %%% mode: latex
350 %%% TeX-master: "gapil"
351 %%% End: