-%% tcpsockadv.tex
+ %% 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
\section{Socket multiplexing}
-\label{sec:TCP_sock_mutiplexing}
+\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
+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 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, 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}.
+
+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
+ connessiioni, 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_outofband}.
+
+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.
+
+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 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.}
-Affronteremo in questa sezione l'utilizzo 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,
-tratteremo qui l'argomento in generale.
+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.