X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=sockctrl.tex;h=7e8a5b611baff469dd1c6aaf389b0ed783d03603;hb=3ad06e8129067dccfa3fad74e7cf6c051231d150;hp=592421dd07c0e84451161068797df5eb3ea6e893;hpb=5b8f42ef99d2884ca02331ee61649ce3b6ec18f5;p=gapil.git diff --git a/sockctrl.tex b/sockctrl.tex index 592421d..7e8a5b6 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -1,6 +1,6 @@ %% sockctrl.tex %% -%% Copyright (C) 2004 Simone Piccardi. Permission is granted to +%% Copyright (C) 2004-2005 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Prefazione", @@ -49,7 +49,7 @@ necessita di compiere questa operazione. \begin{figure}[htb] \centering - \includegraphics[width=10cm]{img/resolver} + \includegraphics[width=9cm]{img/resolver} \caption{Schema di funzionamento delle routine del \textit{resolver}.} \label{fig:sock_resolver_schema} \end{figure} @@ -117,6 +117,7 @@ dell'ordine in cui questi vengono interrogati.\footnote{con le implementazioni funzioni di libreria, prevedendo un ordine di interrogazione predefinito e non modificabile (a meno di una ricompilazione delle librerie stesse).} +\index{\textit{Name~Service~Switch}|(} Per risolvere questa serie di problemi la risoluzione dei nomi a dominio eseguirà dal \textit{resolver} è stata inclusa all'interno di un meccanismo generico per la risoluzione di corrispondenze fra nomi ed informazioni ad essi @@ -192,6 +193,7 @@ quello che conta sono le funzioni classiche che il \textit{resolver} mette a disposizione,\footnote{è cura della implementazione fattane nelle \acr{glibc} tenere conto della presenza del \textit{Name Service Switch}.} e sono queste quelle che tratteremo nelle sezioni successive. +\index{\textit{Name~Service~Switch}|)} \subsection{Le funzioni di interrogazione del \textit{resolver}} @@ -1936,7 +1938,7 @@ socket, mentre l'ultimo argomento \param{optlen},\footnote{questo argomento sez.~\ref{sec:TCP_func_accept}) ed adottato dalle \acr{glibc}.} è la dimensione in byte dei dati presenti all'indirizzo indicato da \param{optval}. Dato che il tipo di dati varia a seconda dell'opzione scelta, occorrerà -individuare qual'è quello che deve essere usato, ed utilizzare le opportune +individuare qual è quello che deve essere usato, ed utilizzare le opportune variabili. La gran parte delle opzioni utilizzano per \param{optval} un valore intero, se @@ -2064,66 +2066,27 @@ usato per \param{optval} ed una breve descrizione del significato delle singole opzioni sulla sesta. -Dato che le descrizioni di tab.~\ref{tab:sock_opt_socklevel} sono estremamente -sommarie, vale la pena entrare in dettagli maggiori; questo ci consentirà -anche di trattare i vari casi particolari, dato che nonostante queste opzioni -siano indicate al livello generico, alcune di esse han senso solo per alcuni -tipi di socket. L'elenco dettagliato del significato di ciascuna di esse è -allora il seguente: -\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}} -\item[\const{SO\_KEEPALIVE}] una connessione può restare attiva se non viene - effettuato alcun traffico su di essa; in certi casi però può essere utile - controllarne lo stato per accorgersi di eventuali problemi. Per questo, se - si imposta questa opzione, è 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), ed utilizza per - \param{optval} un intero usato come valore logico. - - L'opzione 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à; tutto - ciò viene effettuato dal 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: il primo è quello in cui la macchina remota è caduta ed è stata - riavviata, per 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 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 - 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 \errcode{ETIMEDOUT}. Se invece si riceve in risposta ad uno di - questi messaggi un pacchetto ICMP di destinazione irraggiungibile, 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 - 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 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}. - +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 +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 +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 + principalmente con il TCP). L'opzione utilizza per \param{optval} un intero + usato come valore logico. Maggiori dettagli sul suo funzionamento sono + forniti in sez.~\ref{sec:sock_options_main}. \item[\const{SO\_OOBINLINE}] se questa opzione viene abilitata i dati \textit{out-of-band} vengono inviati direttamente nel flusso di dati del @@ -2203,9 +2166,10 @@ allora il seguente: state rimosse con il passaggio al 2.2; è consigliato correggere i programmi piuttosto che usare questa funzione. -\item[\const{SO\_PASSCRED}] questa opzione abilita sui socket unix-domain la - ricezione dei messaggi di controllo di tipo \const{SCM\_CREDENTIALS}. Prende - come \param{optval} un intero usato come valore logico. +\item[\const{SO\_PASSCRED}] questa opzione abilita sui socket unix-domain + (vedi sez.~\ref{sec:unix_socket}) la ricezione dei messaggi di controllo di + tipo \const{SCM\_CREDENTIALS}. Prende come \param{optval} un intero usato + come valore logico. \item[\const{SO\_PEERCRED}] questa opzione restituisce le credenziali del processo remoto connesso al socket; l'opzione è disponibile solo per socket @@ -2214,12 +2178,11 @@ allora il seguente: sez.~\ref{sec:unix_socket_xxx}). \item[\const{SO\_BINDTODEVICE}] questa opzione permette di \textsl{legare} il - socket ad una particolare interfaccia interfaccia, in modo che esso possa - ricevere ed inviare pacchetti solo su quella. L'opzione richiede per - \param{optval} il puntatore ad una stringa contenente il nome - dell'interfaccia (ad esempio \texttt{eth0}); se si utilizza una stringa - nulla o un valore nullo per \param{optlen} si rimuove un precedente - collegamento. + socket ad una particolare interfaccia, in modo che esso possa ricevere ed + inviare pacchetti solo su quella. L'opzione richiede per \param{optval} il + puntatore ad una stringa contenente il nome dell'interfaccia (ad esempio + \texttt{eth0}); utilizzando una stringa nulla o un valore nullo per + \param{optlen} si può rimuovere un precedente collegamento. Il nome della interfaccia deve essere specificato con una stringa terminata da uno zero e di lunghezza massima pari a \const{IFNAMSIZ}; l'opzione è @@ -2227,19 +2190,18 @@ allora il seguente: famiglia \const{AF\_INET}; non è invece supportata per i \textit{packet socket} (vedi sez.~\ref{cha:advanced_socket_xxx}). - \item[\const{SO\_DEBUG}] questa opzione abilita il debugging delle operazioni dei socket; l'opzione utilizza per \param{optval} un intero usato come valore logico, e può essere utilizzata solo da un processo con i privilegi di amministratore (in particolare con la \textit{capability} \const{CAP\_NET\_ADMIN}). L'opzione necessita inoltre dell'opportuno supporto nel kernel;\footnote{deve cioè essere definita la macro di - preprocessore \texttt{SOCK\_DEBUGGING} nel file \file{include/net/sock.h} + preprocessore \macro{SOCK\_DEBUGGING} nel file \file{include/net/sock.h} dei sorgenti del kernel, questo è sempre vero nei kernel delle serie superiori alla 2.3, per i kernel delle serie precedenti invece è necessario aggiungere a mano detta definizione; è inoltre possibile abilitare anche il tracciamento degli stati del TCP definendo la macro - \texttt{STATE\_TRACE} in \file{include/net/tcp.h}.} quando viene + \macro{STATE\_TRACE} in \file{include/net/tcp.h}.} quando viene abilitata una serie di messaggi con le informazioni di debug vengono inviati direttamente al sistema del kernel log.\footnote{si tenga presente che il comportamento è diverso da quanto avviene con BSD, dove l'opzione opera @@ -2248,60 +2210,14 @@ allora il seguente: programma, \cmd{trpt}.} \item[\const{SO\_REUSEADDR}] questa opzione permette di eseguire la funzione - \func{bind} su indirizzi locali che siano già in uso; l'opzione utilizza per - \param{optval} un intero usato come valore logico. Questa opzione modifica - il comportamento normale dell'interfaccia dei socket che fa fallire - l'esecuzione della funzione \func{bind} con un errore di + \func{bind} su indirizzi locali che siano già in uso da altri socket; + l'opzione utilizza per \param{optval} un intero usato come valore logico. + Questa opzione modifica il comportamento normale dell'interfaccia dei socket + che fa fallire l'esecuzione della funzione \func{bind} con un errore di \errcode{EADDRINUSE} quando l'indirizzo locale\footnote{più propriamente il controllo viene eseguito sulla porta.} è già in uso da parte di un altro - socket. - - Come Stevens sottolinea in \cite{UNP1} si distinguono quattro casi per - l'utilizzo di questa opzione; il primo è quello in cui un server è terminato - ma esistono ancora dei processi figli che mantengono attiva almeno una - connessione remota che utilizza l'indirizzo locale; quando si riavvia il - server questo viene bloccato sulla chiamata a \func{bind} dato che la porta - è ancora utilizzata in una connessione esistente.\footnote{questa è una - delle domande più frequenti sui newsgroup dedicati allo sviluppo, in - quanto è piuttosto comune in questa situazione quando si sta sviluppando - un server che si ferma e si riavvia in continuazione.} Inoltre se si usa - il protocollo TCP questo può avvenire anche dopo che l'ultimo processo - figlio è terminato, dato che la connessione può restare attiva anche dopo la - chiusura del socket mantenendosi nello stato \texttt{TIME\_WAIT}. - - Usando \const{SO\_REUSEADDR} fra la chiamata a \func{socket} e quella a - \func{bind} si consente a quest'ultima di avere comunque successo anche se - la connessione è attiva (o nello stato texttt{TIME\_WAIT}). È bene però - ricordare (si riveda quanto detto in sez.~\ref{sec:TCP_time_wait}) che la - presenza dello stato \texttt{TIME\_WAIT} ha una ragione, ed infatti se si - usa questa opzione esiste sempre una probabilità, anche se estremamente - remota,\footnote{perché ciò avvenga infatti non solo devono coincidere gli - indirizzi IP e le porte degli estremi della nuova connessione, ma anche i - numeri di sequenza dei pacchetti, e questo è estremamente improbabile.} - che eventuali pacchetti rimasti intrappolati in una precedente connessione - possano finire fra quelli di una nuova. - - Il secondo caso in cui viene usata questa opzione è quando si ha una - macchina cui sono assegnati diversi numeri IP (o come suol dirsi - \textit{multi-homed}) e si vuole porre in ascolto sulla stessa porta un - programma diverso (o una istanza diversa dello stesso programma) per - indirizzi IP diversi. Si ricordi infatti che è sempre possibile indicare a - \func{bind} di collegarsi solo su di un indirizzo specifico; in tal caso se - un altro programma cerca di riutilizzare la stessa porta (anche specificando - un indirizzo diverso) otterrà un errore a meno di non aver preventivamente - impostato \const{SO\_REUSEADDR}. Usando questa opzione diventa anche - possibile eseguire \func{bind} sull'indirizzo generico, e questo permetterà - il collegamento per tutti gli indirizzi (di quelli presenti) per i quali la - porta risulti libera. Infine si tenga presente che con il protocollo TCP non - è mai possibile far partire server che eseguano \func{bind} sullo stesso - indirizzo e la stessa porta, cioè ottenere quello che viene chiamato un - \textit{completely duplicate binding}. - - Il terzo impiego è simile al precedente e prevede l'uso di \func{bind} - all'interno dello stesso programma per associare indirizzi diversi a socket - diversi. Vale in questo caso quanto detto in precedenza, l'unica differenza - è che in questo caso le diverse chiamate a \func{bind} sono eseguite - all'interno dello stesso programma. + 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 @@ -2317,28 +2233,355 @@ allora il seguente: \item[\const{SO\_DONTROUTE}] questa opzione forza l'invio diretto dei pacchetti del socket, saltando ogni processo relativo all'uso della tabella - di routing del kernel. Prende come \param{optval} un intero usato come - valore logico. + di routing del kernel. Prende per \param{optval} un intero usato come valore + logico. + +\item[\const{SO\_BROADCAST}] questa opzione abilita il \textit{broadcast}; + quanto abilitata i socket di tipo \const{SOCK\_DGRAM} riceveranno i + pacchetti inviati all'indirizzo di broadcast, e potranno scrivere pacchetti + 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 + connessioni (è pertanto usata con i socket TCP ed ignorata per UDP) e + modifica il comportamento delle funzioni \func{close} e \func{shutdown}. + L'opzione richiede che l'argomento \param{optval} sia una struttura di tipo + \struct{linger}, definita in \texttt{sys/socket.h} ed illustrata in + fig.~\ref{fig:sock_linger_struct}. Maggiori dettagli sul suo funzionamento + sono forniti in sez.~\ref{sec:sock_options_main}. + +\item[\const{SO\_PRIORITY}] questa opzione permette di impostare le priorità + per tutti i pacchetti che sono inviati sul socket, prende per \param{optval} + un valore intero. Con questa opzione il kernel usa il valore per ordinare le + priorità sulle code di rete,\footnote{questo richiede che sia abilitato il + sistema di \textit{Quality of Service} disponibile con le opzioni di + routing avanzato.} i pacchetti con priorità più alta vengono processati + per primi, in modalità che dipendono dalla disciplina di gestione della + coda. Nel caso di protocollo IP questa opzione permette anche di impostare i + valori del campo \textit{type of service} (noto come TOS, vedi + sez.~\ref{sec:IP_xxx}) per i pacchetti uscenti. Per impostare una priorità + al di fuori dell'intervallo di valori fra 0 e 6 sono richiesti i privilegi + di amministratore con la capability \const{CAP\_NET\_ADMIN}. + +\item[\const{SO\_ERROR}] questa opzione riceve un errore presente sul socket; + può essere utilizzata soltanto con \func{getsockopt} e prende per + \param{optval} un valore intero. +\end{basedescript} + + +\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. + +\index{\texttt{SO\_KEEPALIVE} (costante)|(} +La prima opzione da approfondire è \const{SO\_KEEPALIVE}, che come accennato +permette di controllare automaticamente lo stato di una connessione. Una +connessione infatti può restare attiva anche se non viene effettuato alcun +traffico su di essa, ma in certi casi però può essere utile controllarne lo +stato per accorgersi di eventuali problemi. + +Per questo, se si imposta questa opzione, è 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), ed +utilizza per \param{optval} un intero usato come valore logico. + +L'opzione 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à; tutto ciò +viene effettuato dal 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: +il primo è quello in cui la macchina remota è caduta ed è stata riavviata, per +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 +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 + 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 +\errcode{ETIMEDOUT}. Se invece si riceve in risposta ad uno di questi messaggi +un pacchetto ICMP di destinazione irraggiungibile, 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 +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 +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}. +\index{\texttt{SO\_KEEPALIVE} (costante)|)} + + +\index{\texttt{SO\_REUSEADDR} (costante)|(} +La seconda opzione da approfondire è \const{SO\_REUSEADDR}. Come Stevens +sottolinea in \cite{UNP1} si distinguono quattro casi per l'utilizzo di questa +opzione; il primo è quello in cui un server è terminato ma esistono ancora dei +processi figli che mantengono attiva almeno una connessione remota che +utilizza l'indirizzo locale. Quando si riavvia il server questo viene bloccato +sulla chiamata a \func{bind} dato che la porta è ancora utilizzata in una +connessione esistente.\footnote{questa è una delle domande più frequenti sui + newsgroup dedicati allo sviluppo, in quanto è piuttosto comune in questa + situazione quando si sta sviluppando un server che si ferma e si riavvia in + continuazione.} Inoltre se si usa il protocollo TCP questo può avvenire +anche dopo che l'ultimo processo figlio è terminato, dato che la connessione +può restare attiva anche dopo la chiusura del socket mantenendosi nello stato +\texttt{TIME\_WAIT}. + +Usando \const{SO\_REUSEADDR} fra la chiamata a \func{socket} e quella a +\func{bind} si consente a quest'ultima di avere comunque successo anche se la +connessione è attiva (o nello stato \texttt{TIME\_WAIT}). È bene però +ricordare (si riveda quanto detto in sez.~\ref{sec:TCP_time_wait}) che la +presenza dello stato \texttt{TIME\_WAIT} ha una ragione, ed infatti se si usa +questa opzione esiste sempre una probabilità, anche se estremamente +remota,\footnote{perché ciò avvenga infatti non solo devono coincidere gli + indirizzi IP e le porte degli estremi della nuova connessione, ma anche i + numeri di sequenza dei pacchetti, e questo è estremamente improbabile.} che +eventuali pacchetti rimasti intrappolati in una precedente connessione possano +finire fra quelli di una nuova. + +Il secondo caso in cui viene usata questa opzione è quando si ha una macchina +cui sono assegnati diversi numeri IP (o come suol dirsi \textit{multi-homed}) +e si vuole porre in ascolto sulla stessa porta un programma diverso (o una +istanza diversa dello stesso programma) per indirizzi IP diversi. Si ricordi +infatti che è sempre possibile indicare a \func{bind} di collegarsi solo su di +un indirizzo specifico; in tal caso se un altro programma cerca di +riutilizzare la stessa porta (anche specificando un indirizzo diverso) otterrà +un errore a meno di non aver preventivamente impostato \const{SO\_REUSEADDR}. +Usando questa opzione diventa anche possibile eseguire \func{bind} +sull'indirizzo generico, e questo permetterà il collegamento per tutti gli +indirizzi (di quelli presenti) per i quali la porta non risulti occupata da +una precedente chiamata più specifica. Infine si tenga presente che con il +protocollo TCP non è mai possibile far partire server che eseguano \func{bind} +sullo stesso indirizzo e la stessa porta, cioè ottenere quello che viene +chiamato un \textit{completely duplicate binding}. + +Il terzo impiego è simile al precedente e prevede l'uso di \func{bind} +all'interno dello stesso programma per associare indirizzi locali diversi a +socket diversi. In genere questo viene fatto per i socket UDP quando è +necessario ottenere l'indirizzo a cui sono rivolte le richieste del client ed +il sistema non supporta l'opzione \const{IP\_RECVDSTADDR};\footnote{nel caso + di Linux questa opzione è stata supportata per in certo periodo nello + sviluppo del kernel 2.1.x, ma è in seguito stata soppiantata dall'uso di + \const{IP\_PKTINFO} (vedi sez.~\ref{sec:sock_ipv4_options}).} in tale modo +si può sapere a quale socket corrisponde un certo indirizzo. Non ha senso 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 +\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, +in cui i pacchetti vengono scambiati direttamente fra due applicazioni; ma +quando un sistema supporta il traffico in multicast, in cui una applicazione +invia i pacchetti a molte altre (vedi sez.~\ref{sec:multicast_xxx}), allora ha +senso che su una macchina i pacchetti provenienti dal traffico in multicast +possano essere ricevuti da più applicazioni\footnote{l'esempio classico di + traffico in multicast è quello di uno streaming di dati (audio, video, + ecc.), l'uso del multicast consente in tal caso di trasmettere un solo + pacchetto, che potrà essere ricevuto da tutti i possibili destinatari + (invece di inviarne un duplicato a ciascuno); in questo caso è perfettamente + logico aspettarsi che sulla stessa macchina più utenti possano lanciare un + programma che permetta loro di ricevere gli stessi dati.} o da diverse +istanze della stessa applicazione. + +In questo caso utilizzando \const{SO\_REUSEADDR} si consente ad una +applicazione eseguire \func{bind} sulla stessa porta ed indirizzo usata da +un'altra, così che anche essa possa ricevere gli stessi pacchetti (chiaramente +la cosa non ha alcun senso per i socket TCP, ed infatti in questo tipo di +applicazione è normale l'uso del protovollo UDP). La regola è che quando si +hanno più applicazioni che hanno eseguito \func{bind} sulla stessa porta, di +tutti pacchetti destinati ad un indirizzo di broadcast o di multicast viene +inviata una copia a ciascuna applicazione. Non è definito invece cosa accade +qualora il pacchetto sia destinato ad un indirizzo normale (unicast). + +Essendo questo un caso particolare in alcuni sistemi (come BSD) è stata +introdotta una opzione ulteriore, \const{SO\_REUSEPORT} che richiede che detta +opzione sia specificata per tutti i socket per i quali si vuole eseguire il +\textit{completely duplicate binding}. Nel caso di Linux questa opzione non +esiste, ma il comportamento di \const{SO\_REUSEADDR} è analogo, sarà cioè +possibile effettuare un \textit{completely duplicate binding} ed ottenere il +successo di \func{bind} su un socket legato allo stesso indirizzo e porta solo +se il primo programma che ha eseguito \func{bind} su di essi ha impostato +questa opzione.\footnote{Questa restrizione permette di evitare il cosiddetto + \textit{port stealing}, in cui un programma, usando \const{SO\_REUSEADDR}, + può collegarsi ad una porta già in uso e ricevere i pacchetti destinati ad + un altro programma; con questa caratteristica ciò è possibile soltanto se il + primo programma a consentirlo, avendo usato fin dall'inizio + \const{SO\_REUSEADDR}.} +\index{\texttt{SO\_REUSEADDR} (costante)|)} + + +\index{\texttt{SO\_LINGER} (costante)|(} 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. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includestruct{listati/linger.h} + \end{minipage} + \caption{La struttura \structd{linger} richiesta come valore dell'argomento + \param{optval} per l'impostazione dell'opzione dei socket + \const{SO\_LINGER}.} + \label{fig:sock_linger_struct} +\end{figure} -\item[\const{SO\_BROADCAST}] +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 +\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}. +\index{\texttt{SO\_LINGER} (costante)|)} -\item[\const{SO\_SNDBUF}] -\item[\const{SO\_RCVBUF}] -\item[\const{SO\_LINGER}] -\item[\const{SO\_PRIORITY}] +\subsection{Le opzioni per il protocollo IPv4} +\label{sec:sock_ipv4_options} -\item[\const{SO\_ERROR}] +Il secondo insieme di opzioni dei socket che tratteremo è quello relativo ai +socket che usano il protocollo IPv4.\footnote{come per le precedenti opzioni + generiche una descrizione di esse è disponibile nella settima sezione delle + pagine di manuale, nel caso specifico la documentazione si può consultare + con \texttt{man 7 ip}.} Se si vuole operare su queste opzioni generiche il +livello da utilizzare è \const{SOL\_IP}; si è riportato un elenco di queste +opzioni in tab.~\ref{tab:sock_opt_iplevel}. + + +\begin{table}[!htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|c|c|c|l|l|} + \hline + \textbf{Opzione}&\texttt{get}&\texttt{set}&\textbf{flag}&\textbf{Tipo}& + \textbf{Descrizione}\\ + \hline + \hline + \const{IP\_OPTIONS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Imposta o riceve le opzioni di IP.\\ + \const{IP\_PKTINFO}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Passa un messaggio di informazione.\\ + \const{IP\_RECVTOS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Passa un messaggio col campo TOS.\\ + \const{IP\_RECVTTL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Passa un messaggio col campo TTL.\\ + \const{IP\_RECVOPTS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Passa un messaggio con le opzioni IP.\\ + \const{IP\_RETOPTS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Passa un messaggio con le opzioni IP non + trattate.\\ + \const{IP\_TOS}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Imposta il valore del campo TOS.\\ + \const{IP\_TTL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Imposta il valore del campo TTL.\\ + \const{IP\_HDRINCL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Passa l'intestazione di IP nei dati.\\ + \const{IP\_RECVERR}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Abilita la gestione degli errori.\\ + \const{IP\_MTU\_DISCOVER}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Imposta il Path MTU Discovery.\\ + \const{IP\_MTU}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Legge il valore attuale della MTU.\\ + \const{IP\_ROUTER\_ALERT}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Imposta l'opzione \textit{IP router alert} sui + pacchetti.\\ + \const{IP\_MULTICAST\_TTL}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Imposta il TTL per i pacchetti multicast.\\ + \const{IP\_MULTICAST\_LOOP}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Controlla il reinvio a se + stessi dei dati di multicast.\\ + \const{IP\_ADD\_MEMBERSHIP}& &$\bullet$&$\bullet$&\texttt{int}& + Si unisce a un gruppo di multicast.\\ + \const{IP\_DROP\_MEMBERSHIP}& &$\bullet$&$\bullet$&\texttt{int}& + Si sgancia da un gruppo di multicast.\\ + \const{IP\_MULTICAST\_IF}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + Imposta l'interfaccia locale di un socket + multicast.\\ + \hline + \end{tabular} + \caption{Le opzioni disponibili al livello \const{SOL\_IP}.} + \label{tab:sock_opt_iplevel} +\end{table} + + +Le descrizioni di tab.~\ref{tab:sock_opt_iplevel} sono estremamente succinte, +una maggiore quantità di dettagli su queste opzioni è fornito nel seguente +elenco: +\begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}} +\item[\const{IP\_MULTICAST\_LOOP}] L'opzione consente di decidere se i dati + che si inviano su un socket usato con il multicast vengano ricevuti anche + sulla stessa macchina da cui li si stanno inviando. Prende per + \param{optval} un intero usato come valore logico. + + In generale se si vuole che eventuali client possano ricevere i dati che si + inviano occorre che questa funzionalità sia abilitata (come avviene di + default). Qualora però non si voglia generare traffico per dati che già sono + disponibili l'uso di questa opzione permette di disabilitare questo tipo di + traffico. \end{basedescript} + \section{Altre funzioni di controllo} \label{sec:sock_ctrl_func} @@ -2378,7 +2621,45 @@ certo tipo o di tutti quelli che usano un certo protocollo) rispetto alle funzioni viste finora che consentono di controllare quelle di un singolo socket. +Le opzioni disponibili per le proprietà della rete sono riportate nella +gerarchia dei valori impostabili con \func{sysctl}, sotto il nodo +\texttt{net}, o, se acceduti tramite l'interfaccia del filesystem +\texttt{/proc}, sotto \texttt{/proc/sys/net}. In genere sotto questa directory +compaiono le sottodirectory (corrispondenti ad altrettanti sottonodi per +\func{sysctl}) relative ai vari protocolli e tipi di interfacce su cui è +possibile intervenire; un contenuto tipico è il seguente: +\begin{verbatim} +/proc/sys/net/ +|-- core +|-- ethernet +|-- ipv4 +|-- ipv6 +|-- irda +|-- token-ring +`-- unix +\end{verbatim} + + +Nella directory \texttt{/proc/sys/net/core} sono disponibili le opzioni +generiche dei socket, descritte anche nella rispettiva pagina di +manuale.\footnote{quella accessibile con \texttt{man 7 socket}.} Queste sono: +\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}} +\item[\texttt{rmem\_default}] imposta la dimensione di default del buffer di + lettura (cioè per i dati in ingresso) dei socket. +\item[\texttt{rmem\_max}] imposta la dimensione massima che si può assegnare al + buffer di ingresso dei socket attraverso l'uso dell'opzione + \const{SO\_RCVBUF}. +\item[\texttt{wmem\_default}] imposta la dimensione di default del buffer di + scrittura (cioè per i dati in uscita) dei socket. +\item[\texttt{wmem\_max}] imposta la dimensione massima che si può assegnare al + buffer di uscita dei socket attraverso l'uso dell'opzione + \const{SO\_SNDBUF}. +\item[\texttt{message\_cost}] +\item[\texttt{message\_burst}] +\item[\texttt{netdev\_max\_backlog}] +\item[\texttt{optmem\_max}] +\end{basedescript} %%% Local Variables: