Completata e rivista la trattazione di SO_LINGER.
[gapil.git] / sockctrl.tex
index c1b8d2783fb9e11cc1170d9a86188e20d19399d8..b0cc66c6b02f34a8a346a30865f74858a5742ca5 100644 (file)
@@ -2066,22 +2066,15 @@ un valore logico. Si 
 usato per \param{optval} ed una breve descrizione del significato delle
 singole opzioni sulla sesta.
 
-
-Questo ci consentirà anche
-di trattare approfonditamente alcune opzioni che, nonostante siano
-classificate fra quelle generiche, hanno un significato effettivo solo per
-alcuni tipi di socket.TCP/IP.  L'elenco dettagliato del significato delle
-opzioni generiche dei socket è allora il seguente:
-
-
 Le descrizioni delle opzioni presenti in tab.~\ref{tab:sock_opt_socklevel}
 sono estremamente sommarie, è perciò necessario fornire un po' più di
-informazioni; alcune opzioni comunque hanno una notevole rilevanza nella
+informazioni. Alcune opzioni inoltre hanno una notevole rilevanza nella
 gestione dei socket, e pertanto il loro utilizzo sarà approfondito
-separatamente in sez.~\ref{sec:sock_options_main}. Quello che segue pertanto è
-soltanto un elenco più dettagliato di quanto scritto in
+separatamente in sez.~\ref{sec:sock_options_main}. Quello che segue è quindi
+soltanto un elenco più dettagliato della breve descrizione di
 tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
 \begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}}
+
 \item[\const{SO\_KEEPALIVE}] questa opzione abilita un meccanismo di verifica
   della persistenza di una connessione associata al socket (ed è pertanto
   effettiva solo sui socket che supportano le connessioni, ed è usata
@@ -2098,7 +2091,6 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
   supportino i dati \textit{out-of-band} (non ha senso per socket UDP ad
   esempio), ed utilizza per \param{optval} un intero usato come valore logico.
 
-
 \item[\const{SO\_RCVLOWAT}] questa opzione imposta il valore che indica il
   numero minimo di byte che devono essere presenti nel buffer di ricezione
   perché il kernel passi i dati all'utente, restituendoli ad una \func{read} o
@@ -2108,7 +2100,6 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
   essere cambiato; \func{getsockopt} leggerà questo valore mentre
   \func{setsockopt} darà un errore di \errcode{ENOPROTOOPT}. 
 
-
 \item[\const{SO\_SNDLOWAT}] questa opzione imposta il valore che indica il
   numero minimo di byte che devono essere presenti nel buffer di scrittura
   perché il kernel li invii al protocollo successivo, consentendo ad una
@@ -2119,7 +2110,6 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
   sempre 1 e non può essere cambiato; \func{getsockopt} leggerà questo valore
   mentre \func{setsockopt} darà un errore di \errcode{ENOPROTOOPT}.
 
-
 \item[\const{SO\_RCVTIMEO}] l'opzione permette di impostare un tempo massimo
   sulle operazioni di lettura da un socket, e prende per \param{optval} una
   struttura di tipo \struct{timeval} (vedi fig.~\ref{fig:sys_timeval_struct})
@@ -2220,7 +2210,6 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
   socket.  Maggiori dettagli sul suo funzionamento sono forniti in
   sez.~\ref{sec:sock_options_main}.
 
-
 \item[\const{SO\_TYPE}] questa opzione permette di leggere il tipo di socket
   su cui si opera; funziona solo con \func{getsockopt}, ed utilizza per
   \param{optval} un intero in cui verrà restituto il valore numerico che lo
@@ -2243,20 +2232,17 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
   su tale indirizzo.  Prende per \param{optval} un intero usato come valore
   logico. L'opzione non ha effetti su un socket di tipo \const{SOCK\_STREAM}.
 
-
 \item[\const{SO\_SNDBUF}] questa opzione imposta la dimenzione del buffer di
   uscita del socket. Prende per \param{optval} un intero indicante il numero
   di byte. Il valore di default ed il valore massimo che si può specificare
   come argomento per questa opzione sono impostabili tramiti gli opportuni
   valori di \func{sysctl} (vedi sez.~\ref{sec:sock_sysctl}).
 
-
 \item[\const{SO\_RCVBUF}] questa opzione imposta la dimenzione del buffer di
   ingresso del socket. Prende per \param{optval} un intero indicante il numero
   di byte. Il valore di default ed il valore massimo che si può specificare
   come argomento per questa opzione sono impostabili tramiti gli opportuni
   valori di \func{sysctl} (vedi sez.~\ref{sec:sock_sysctl}).
-   
 
 \item[\const{SO\_LINGER}] questa opzione controlla le modalità con cui viene
   chiuso un socket quando si utilizza un protocollo che supporta le
@@ -2289,11 +2275,12 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
 \subsection{Le uso delle principali opzioni dei socket}
 \label{sec:sock_options_main}
 
-L'elenco sintetico delle caratteristiche delle opzioni dei socket riportato in
-sez.~\ref{sec:sock_generic_options} non è sufficientemente dettagliato per
-permetterci di approfondire il significato di alcune di esse, che assumono
-grande importanza nella programmazione dei socket. Per questo motivo
-tratteremo ulteriormente l'uso di alcune di esse in questa sezione.
+La descrizione sintetica del significato delle opzioni generiche dei socket,
+riportata nell'elenco in sez.~\ref{sec:sock_generic_options}, non è
+sufficientemente dettagliata per permetterci di approfondire tutti le
+funzionalità che alcune di esse possono controllare, alcune delle quali hanno
+un rilevanza notevole nella programmazione dei socket. Per questo motivo
+tratteremo nei dettagli le principali opzioni in questa sezione.
 
 
 \index{\texttt{SO\_KEEPALIVE} (costante)|(} 
@@ -2301,22 +2288,25 @@ tratteremo ulteriormente l'uso di alcune di esse in questa sezione.
 
 La prima opzione da approfondire è \const{SO\_KEEPALIVE} che permette di
 tenere sotto controllo lo stato di una connessione. Una connessione infatti
-resta attiva anche quando non viene effettuato alcun traffico su di essa, per
-cui un crollo della stessa potrebbe passare inosservato.
+resta attiva anche quando non viene effettuato alcun traffico su di essa,
+questo può comportare che un crollo della connessione, qualora avvenisse ad
+esempio in conseguenza di una interruzione completa della rete, potrebbe
+passare inosservato.
 
-Se si imposta questa opzione, è cura del kernel inviare degli appositi
-messaggi sulla rete (detti appunto \textit{keep-alive}) per verificare se la
+Se si imposta questa opzione, è invece cura del kernel inviare degli appositi
+messaggi sulla rete, detti appunto \textit{keep-alive}, per verificare se la
 connessione è attiva.  L'opzione funziona soltanto con socket che supportino
 le connessioni (non ha senso per socket UDP ad esempio) e si applica
 principalmente ai socket TCP.
 
 Con le impostazioni di default (che sono riprese da BSD) Linux emette un
-messaggio di \textit{keep-alive} verso l'altro capo della connessione se
-questa è rimasta senza traffico per più di due ore. Se è tutto a posto il
-messaggio viene ricevuto e verrà emesso un segmento ACK di risposta, alla cui
-ricezione ripartirà un'altro ciclo di attesa per altre due ore di inattività;
-il tutto avviene all'interno del kernel e le applicazioni non riceveranno
-nessun dato.
+messaggio di \textit{keep-alive}\footnote{in sostanza un segmento ACK vuoto,
+  cui sarà risposto con un altro segmento ACK vuoto.} verso l'altro capo della
+connessione se questa è rimasta senza traffico per più di due ore. Se è tutto
+a posto il messaggio viene ricevuto e verrà emesso un segmento ACK di
+risposta, alla cui ricezione ripartirà un'altro ciclo di attesa per altre due
+ore di inattività; il tutto avviene all'interno del kernel e le applicazioni
+non riceveranno nessun dato.
 
 In caso di problemi invece si possono avere i due casi già illustrati in
 sez.~\ref{sec:TCP_conn_crash} per il caso di terminazione prococe del server:
@@ -2324,18 +2314,20 @@ il primo 
 cui dopo il riavvio la connessione non viene più riconosciuta,\footnote{si
   ricordi che un normale riavvio non ha questo effetto, in quanto si passa per
   la chiusura del processo, che chiude anche il socket inviando un segmento
-  FIN all'altro capo della connessione.} e si otterrà come risposta un RST. In
+  FIN all'altro capo della connessione.} in questo caso all'invio del
+messaggio di \textit{keep-alive} si otterrà come risposta un segmento RST che
+indica che l'altro capo non riconosce più l'esistenza della connessione. In
 tal caso il socket viene chiuso dopo aver impostato un errore
 \errcode{ECONNRESET}.
 
 Se invece non viene ricevuta nessuna risposta (indice che la macchina non è
 più raggiungibile) l'emissione dei messaggi viene ripetuta ad intervalli di 75
-secondi ad un massimo di 9 volte\footnote{entrambi questi valori possono
+secondi per un massimo di 9 volte\footnote{entrambi questi valori possono
   essere opportunamente modificati con gli opportuni parametri illustrati in
   sez.~\ref{sec:sock_sysctl}, si tenga presente che però questo vale a livello
-  di kernel ed i valori saranno applicati a \textsl{tutti} i socket.} (per un
-totale di 11 minuti e 15 secondi) dopo di che, se non si è ricevuta nessuna
-risposta, il socket viene chiuso dopo aver impostato un errore di
+  di kernel ed i suddetti valori saranno applicati a \textsl{tutti} i socket.}
+(per un totale di 11 minuti e 15 secondi) dopo di che, se non si è ricevuta
+nessuna risposta, il socket viene chiuso dopo aver impostato un errore di
 \errcode{ETIMEDOUT}. Qualora la connessione si sia ristabilita e si riceva un
 successivo messaggio di risposta il ciclo riparte come se niente fosse
 avvenuto.  Infine se invece si riceve come risposta un pacchetto ICMP di
@@ -2343,17 +2335,23 @@ destinazione irraggiungibile (vedi sez.~\ref{sec:icmp_protocol_xxx}), verr
 restituito l'errore corrispondente.
 
 In generale questa opzione serve per individuare una caduta della
-connessione,\footnote{il crash di un processo di nuovo comporta la chiusura di
-  tutti i file che aveva aperti e la relativa emissione degli opportuni
-  segmenti FIN nel caso dei socket.} e viene usata sui server per evitare di
+connessione\footnote{la terminazione di un processo di nuovo comporta la
+  chiusura di tutti i file che aveva aperti e la relativa emissione degli
+  opportuni segmenti FIN nel caso dei socket.} anche quando non si sta facendo
+traffico su di essa.  In genere viene usata sui server per evitare di
 mantenere impegnate le risorse dedicate a trattare delle connessioni in realtà
-terminate.  Abilitandola le connessioni effettivamente terminate vengono
-chiuse ed una \func{select} potrà rilevare la conclusione delle stesse e
+già terminate (quelle che vengono anche chiamate connessioni
+\textsl{semi-aperte}) in cui il server è in attesa di dati in ingresso che non
+arriveranno mai perché il client sull'altro capo non è più attivo.
+
+Abilitandola le connessioni effettivamente terminate vengono chiuse e ad
+esempio una \func{select} potrà rilevare la conclusione delle stesse e
 ricevere il relativo errore. Si tenga però presente che non si ha la certezza
 assoluta che un errore di \errcode{ETIMEDOUT} corrisponda ad una reale
 conclusione della connessione, il problema potrebbe essere dovuto ad un
 problema di routing che perduri per un tempo maggiore di quello impiegato nei
-vari tentativi di ritrasmissione del \textit{keep-alive}.
+vari tentativi di ritrasmissione del \textit{keep-alive} (anche se questa non
+è una una condizione molto probabile).
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -2363,7 +2361,7 @@ vari tentativi di ritrasmissione del \textit{keep-alive}.
   \normalsize
   \caption{La sezione della nuova versione del server del servizio
     \textit{echo} che prevede l'attivazione del \textit{keepalive} sui
-    socket.} 
+    socket.}
   \label{fig:echod_keepalive_code}
 \end{figure}
 
@@ -2383,7 +2381,6 @@ chiamata a \func{setsockopt} (\texttt{\small 16}).  A seconda del suo valore
 tutte le volta che un processo figlio viene eseguito in risposta ad una
 connessione verrà pertanto eseguita o meno la sezione (\texttt{\small 14--17})
 che esegue l'impostazione di \const{SO\_KEEPALIVE} sul socket connesso.
-
 \index{\texttt{SO\_KEEPALIVE} (costante)|)}
 
 
@@ -2473,7 +2470,6 @@ riportata in fig.~\ref{fig:TCP_echod_fifth}) se ne potr
 valore, per cui in tal caso la successiva chiamata (\texttt{\small 13-17}) a
 \func{setsockopt} attiverà l'opzione \const{SO\_REUSEADDR}.
 
-
 \begin{figure}[!htb] 
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
@@ -2515,7 +2511,7 @@ si pu
 fare questa operazionie per socket TCP dato che su di essi si può sempre
 invocare \func{getsockname} una volta che si è completata la connessione.
 
-Infine il quarto caso è quello in si vuole effettivamente ottenere un
+Infine il quarto caso è quello in cui si vuole effettivamente ottenere un
 \textit{completely duplicate binding}, quando cioè si vuole eseguire
 \func{bind} su un indirizzo ed una porta che sono già \textsl{legati} ad un
 altro socket.  Questo ovviamente non ha senso per il normale traffico di rete,
@@ -2564,10 +2560,11 @@ questa opzione.\footnote{Questa restrizione permette di evitare il cosiddetto
 
 La terza opzione da approfondire è \const{SO\_LINGER}; essa, come il nome
 suggerisce, consente di ``\textsl{indugiare}'' nella chiusura di un socket. Il
-comportamento standard sia di \func{close} che \func{shutdown} è quello di
-terminare immediatamente dopo la chiamata, mentre il procedimento di chiusura
-della connessione e l'invio sulla rete di tutti i dati ancora presenti nei
-buffer viene gestito in sottofondo dal kernel.
+comportamento standard sia di \func{close} che \func{shutdown} è infatti
+quello di terminare immediatamente dopo la chiamata, mentre il procedimento di
+chiusura della connessione (o di un lato di essa) ed il rispettivo invio sulla
+rete di tutti i dati ancora presenti nei buffer, viene gestito in sottofondo
+dal kernel.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -2580,23 +2577,70 @@ buffer viene gestito in sottofondo dal kernel.
   \label{fig:sock_linger_struct}
 \end{figure}
 
-L'uso di \const{SO\_LINGER} permette di modificare (ed eventualmente
-ripristinare) questo comportamento in base ai valori passati nei campi della
-stuttura \struct{linger}.  Fintanto che il valore del campo \var{l\_onoff} di
-\struct{linger} è nullo la modalità che viene impostata (qualunque sia il
-valore di \var{l\_linger}) è quella standard appena illustrata.
-
-Se però si utilizza un valore di \var{l\_onoff} diverso da zero per
-l'impostazione di \const{SO\_LINGER} il comportamento dipende dal valore di
+L'uso di \const{SO\_LINGER} con \func{setsockopt} permette di modificare (ed
+eventualmente ripristinare) questo comportamento in base ai valori passati nei
+campi della stuttura \struct{linger}, illustrata in
+fig.~\ref{fig:sock_linger_struct}.  Fintanto che il valore del campo
+\var{l\_onoff} di \struct{linger} è nullo la modalità che viene impostata
+(qualunque sia il valore di \var{l\_linger}) è quella standard appena
+illustrata; questa combinazione viene utilizzata per riportarsi al
+comportamento normale qualora esso sia stato cambiato da una precedente
+chiamata.
+
+Se si utilizza un valore di \var{l\_onoff} diverso da zero, il comportamento
+alla chiusura viene a dipendere dal valore specificato per il campo
 \var{l\_linger}; se quest'ultimo è nullo l'uso delle funzioni \func{close} e
 \func{shutdown} provoca la terminazione immediata della connessione: nel caso
 di TCP cioè non viene eseguito il procedimento di chiusura illustrato in
-sez.~\ref{sec:TCP_conn_term}, ma viene inviato un segmento di RST che termina
-immediatamente la connessione. Se invece \var{l\_linger} ha un valore diverso
-da zero sia \func{close} che \func{shutdown} si bloccano e non ritornano
-fintanto che non si sia concluso il procedimento di chiusura della
-connessione, o non siano passati il numero di secondi specificati da
-\var{l\_linger}.
+sez.~\ref{sec:TCP_conn_term}, ma tutti i dati ancora presenti nel buffer
+vengono immediatamente scartati e sulla rete viene inviato un segmento di RST
+che termina immediatamente la connessione.
+
+Un esempio di questo comportamento si può abilitare nel nostro client del
+servizio \textit{echo} utilizzando l'opzione \texttt{-r}; riportiamo in
+fig.~\ref{fig:TCP_echo_sixth} la sezione di codice che permette di introdurre
+questa funzionalità,; al solito il codice completo è disponibile nei sorgenti
+allegati.
+
+\begin{figure}[!htb] 
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/TCP_echo_sixth.c}
+  \end{minipage}
+  \normalsize
+  \caption{La sezione del codice del client \textit{echo} che imposta la
+    terminazione immediata della connessione in caso di chiusura.}
+  \label{fig:TCP_echo_sixth}
+\end{figure}
+
+La sezione indicata viene eseguita dopo aver effettuato la connessione e prima
+di chiamare la funzione di gestione, cioè fra le righe (\texttt{\small 12}) e
+(\texttt{\small 13}) del precedente esempio di fig.~\ref{fig:TCP_echo_fifth}.
+Il codice si limita semplicememente a controllare (\texttt{\small 3}) il
+valore della variabile \var{reset} che assegnata nella gestione delle opzioni
+in corrispondenza all'uso di \texttt{-r} nella chiamata del client. Nel caso
+questa sia diversa da zero vengono impostati (\texttt{\small 5--6}) i valori
+della struttura \var{ling} che permettono una terminazione immediata della
+connessine. Questa viene poi usata nella successiva (\texttt{\small 7})
+chiamata a \func{setsockopt}. Al solito si controlla (\texttt{\small 7--10})
+il valore di ritorno e si termina il programma in caso di errore, stampadone
+il valore.
+
+Infine l'ultima possibilità, quella in cui si utilizza effettivamente
+\const{SO\_LINGER} per \textsl{indugiare} nella chiusura, è quella in cui sia
+\var{l\_onoff} che \var{l\_linger} hanno un valore diverso da zero. Se si
+esegue l'impostazione con questi valori sia \func{close} che \func{shutdown}
+si bloccano, nel frattempo viene eseguita la normale procedura di conclusione
+della connessione (quella di sez.~\ref{sec:TCP_conn_term}) ma entrambe le
+funzioni ritornano fintanto che non si sia concluso il procedimento di
+chiusura della connessione, o non sia passato un numero di
+secondi\footnote{questa è l'unità di misura indicata da POSIX ed adottata da
+  Linux, altri kernel possono usare unità di misura diverse, oppure usare il
+  campo \var{l\_linger} come valore logico (ignorandone il valore) per rendere
+  (quando diverso da zero) \func{close} e \func{shutdown} bloccanti fino al
+  completamento della trasmissione dei dati sul buffer.}  pari al valore
+specificato in \var{l\_linger}.
+
 
 
 \index{\texttt{SO\_LINGER} (costante)|)}