From bba36f6db6e48de4fd97f8a1aa15a0d82558e776 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 26 Dec 2004 21:30:35 +0000 Subject: [PATCH] Ancora sulle opzioni dei socket generiche, aggiornando alcuni vecchi riferimenti sbagliati --- sockctrl.tex | 341 ++++++++++++++++++++++++++++++++++++++------ sources/mygetaddr.c | 4 +- sources/mygethost.c | 14 +- tcpsock.tex | 33 ++--- 4 files changed, 329 insertions(+), 63 deletions(-) diff --git a/sockctrl.tex b/sockctrl.tex index ee24c59..2b83e84 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -1872,29 +1872,37 @@ intende operare; per indicare l'opzione da impostare si devono usare i due argomenti successivi, \param{level} e \param{optname}. Come abbiamo visto in sez.~\ref{sec:net_protocols} i protocolli di rete sono strutturati su vari livelli, ed l'interfaccia dei socket può usarne più di uno. Si avranno allora -diverse funzionalità e caratteristiche per ciascun protocollo usato da un -socket, e quindi saranno anche diverse le opzioni che di potranno impostare, a -seconda del \textsl{livello} (trasporto, rete, ecc.) su cui si va ad operare. +funzionalità e caratteristiche diverse per ciascun protocollo usato da un +socket, e quindi saranno anche diverse le opzioni che si potranno impostare +per ciascun socket, a seconda del \textsl{livello} (trasporto, rete, ecc.) su +cui si vuole andare ad operare. Il valore di \param{level} seleziona allora il protocollo su cui vuole -intervenire, e permette di usare per \param{optname} i valori delle opzioni -che sono definite su quel protocollo. Esiste però anche il valore speciale -\const{SOL\_SOCKET} che indica un livello di base e cioè le opzioni -disponibili per qualunque tipo di socket. Per impostare le opzioni relative -alle funzionalità dei singoli protocolli si deve utilizzare il valore numerico -che identifica questi ultimi in \file{/etc/protocols}; più comunemente si -usano le apposite costanti \texttt{SOL\_*} riportate in -tab.~\ref{tab:sock_option_levels}, dove si sono riassunti i valori possibili -per l'argomento \param{level}.\footnote{la notazione in questo caso è, - purtroppo, abbastanza confusa: infatti in Linux il valore si può impostare - sia usando le costanti \texttt{SOL\_*}, che le analoghe \texttt{IPPROTO\_*} - (citate anche da Stevens in \cite{UNP1}); entrambe hanno gli stessi valori - che sono equivalenti ai numeri di protocollo di \file{/etc/protocols}, con - una eccesione specifica, che è quella del protocollo ICMP, per la quale non +intervenire, mentre \param{optname} permette di scegliere su quale delle +opzioni che sono definite per quel protocollo si vuole operare. In sostanza la +selezione di una specifica opzione viene fatta attraverso una coppia di valori +\param{level} e \param{optname} e chiaramente la funzione avrà successo +soltanto se il protocollo in questione prevede quella opzione ed è utilizzato +dal socket. Infine \param{level} prevede anche il valore speciale +\const{SOL\_SOCKET} usato per le opzioni generiche che sono disponibili per +qualunque tipo di socket. + +I valori usati per \param{level}, corrispondenti ad un dato protocollo usato +da un socket, sono quelli corrispondenti al valore numerico che identifica il +suddetto protocollo in \file{/etc/protocols}; dato che la leggibilità di un +programma non trarrebbe certo beneficio dall'uso diretto dei valori numerici, +più comunemente si indica il protocollo tramite le apposite costanti +\texttt{SOL\_*} riportate in tab.~\ref{tab:sock_option_levels}, dove si sono +riassunti i valori che possono essere usati per l'argomento +\param{level}.\footnote{la notazione in questo caso è, purtroppo, abbastanza + confusa: infatti in Linux il valore si può impostare sia usando le costanti + \texttt{SOL\_*}, che le analoghe \texttt{IPPROTO\_*} (citate anche da + Stevens in \cite{UNP1}); entrambe hanno gli stessi valori che sono + equivalenti ai numeri di protocollo di \file{/etc/protocols}, con una + eccesione specifica, che è quella del protocollo ICMP, per la quale non esista una costante, il che è comprensibile dato che il suo valore, 1, è quello che viene assegnato a \const{SOL\_SOCKET}.} - \begin{table}[!htb] \centering \footnotesize @@ -1917,23 +1925,27 @@ per l'argomento \param{level}.\footnote{la notazione in questo caso Il quarto argomento, \param{optval} è un puntatore ad una zona di memoria che contiene i dati che specificano il valore dell'opzione che si vuole passare al -socket (e il tipo di dati varia a seconda dell'opzione), mentre l'ultimo -argomento \param{optlen},\footnote{questo argomento è in realtà sempre di tipo - \ctyp{int}, come era nelle \acr{libc4} e \acr{libc5}; l'uso di - \ctyp{socklen\_t} è stato introdotto da POSIX (valgono le stesse - considerazioni per l'uso di questo tipo di dato fatte in +socket, mentre l'ultimo argomento \param{optlen},\footnote{questo argomento è + in realtà sempre di tipo \ctyp{int}, come era nelle \acr{libc4} e + \acr{libc5}; l'uso di \ctyp{socklen\_t} è stato introdotto da POSIX (valgono + le stesse considerazioni per l'uso di questo tipo di dato fatte in 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 +variabili. La gran parte delle opzioni utilizzano per \param{optval} un valore intero, se -poi l'opzione esprime una condizione logica si deve usare particolare un -valore non nullo per abilitarla ed un valore nullo per disabilitarla. Se -invece l'opzione non prevede di dover ricevere nessun tipo di valore si deve -impostare \param{optval} a \const{NULL}. +poi l'opzione esprime una condizione logica, il valore è sempre un intero, am +si dovrà usare un valore non nullo per abilitarla ed un valore nullo per +disabilitarla. Se invece l'opzione non prevede di dover ricevere nessun tipo +di valore si deve impostare \param{optval} a \const{NULL}. Un piccolo numero +di opzioni però usano dei tipi di dati peculiari, è questo il motivo per cui +\param{optval} è stato definito come puntatore generico. La seconda funzione usata per controllare le proprietà dei socket è -\func{getsockopt}, che serve a leggere i valori delle opzioni dd a farsi -restituire i dati relativi al loro funzionamento; il suo prototipo è: +\funcd{getsockopt}, che serve a leggere i valori delle opzioni dei socket ed a +farsi restituire i dati relativi al loro funzionamento; il suo prototipo è: \begin{functions} \headdecl{sys/socket.h} \headdecl{sys/types.h} @@ -1956,29 +1968,270 @@ restituire i dati relativi al loro funzionamento; il suo prototipo \end{functions} I primi tre argomenti sono identici ed hanno lo stesso significato di quelli -di \func{setsockopt}, mentre \param{optval} in questo caso indica l'indirizzo -a cui andranno scritti i dati letti dal socket, e \param{optlen} è usata come -\textit{value result argument} per indicare la lunghezza del buffer allocato -per \param{optval} e per ricevere indietro la dimensione effettiva dei dati -scritti su di esso. +di \func{setsockopt}, anche se non è detto che tutte le opzioni siano definite +per entrambe le funzioni. In questo caso \param{optval} viene usato per +ricevere le informazioni ed indica l'indirizzo a cui andranno scritti i dati +letti dal socket, infine \param{optlen} diventa un puntatore ad una variabile +che viene usata come \textit{value result argument} per indicare, prima della +chiamata della funzione, la lunghezza del buffer allocato per \param{optval} e +per ricevere indietro, dopo la chiamata della funzione, la dimensione +effettiva dei dati scritti su di esso. Se la dimenzione del buffer allocato +per \param{optval} non è sufficiente si avrà un errore. + \subsection{Le opzioni generiche} \label{sec:sock_generic_options} -Anche se ciascun tipo di socket presenta una serie di caratteristiche -particolari, gestite attraverso delle opzioni specifiche, esiste un insieme -generico di opzioni che possono applicarsi a qualunque tipo di -socket.\footnote{una descrizione di queste opzioni è generalmente disponibile - nella quarta sezione delle pagine di manuale con \texttt{man 4 socket}.} -Come detto in tal caso il livello da scegliere è \const{SOL\_SOCKET} - - - -In generale il valore di \param{optname} viene passato invariato al +Come accennato esiste un insieme generico di opzioni dei socket che possono +applicarsi a qualunque tipo di socket,\footnote{una descrizione di queste + opzioni è generalmente disponibile nella settima sezione delle pagine di + manuale, nel caso specifico la si può consultare con \texttt{man 7 socket}.} +indipendentemente da quale protocollo venga poi utilizzato. Se si vuole +operare su queste opzioni generiche il livello da utilizzare è +\const{SOL\_SOCKET}; si è riportato un elenco di queste opzioni in +tab.~\ref{tab:sock_opt_socklevel}. +\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{SO\_KEEPALIVE}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + controlla l'attività della connessione.\\ + \const{SO\_OOBINLINE}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + lascia in linea i dati \textit{out-of-band}.\\ + \const{SO\_RCVLOWAT} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + basso livello sul buffer di ricezione.\\ + \const{SO\_SNDLOWAT} &$\bullet$&$\bullet$& &\texttt{int}& + basso livello sul buffer di trasmissione.\\ + \const{SO\_RCVTIMEO} &$\bullet$&$\bullet$& &\texttt{timeval}& + timeout in ricezione.\\ + \const{SO\_SNDTIMEO} &$\bullet$&$\bullet$& &\texttt{timeval}& + timeout in trasmissione.\\ + \const{SO\_BSDCOMPAT}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + abilita la compatibilità con BSD.\\ + \const{SO\_PASSCRED} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + abilita la ricezione di credenziali.\\ + \const{SO\_PEERCRED} &$\bullet$& & &\texttt{ucred}& + restituisce le credenziali del processo remoto.\\ + \const{SO\_BINDTODEVICE}&$\bullet$&$\bullet$& &\texttt{char *}& + lega il socket ad un dispositivo.\\ + \const{SO\_DEBUG} &$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + abilita il debugging sul socket.\\ + \const{SO\_REUSEADDR}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + consente il riutilizzo di un indirizzo locale.\\ + \const{SO\_TYPE} &$\bullet$& & &\texttt{int}& + restituisce il tipo di socket.\\ + \const{SO\_ACCEPTCONN}&$\bullet$& & &\texttt{int}& + indica se il socket è in ascolto.\\ + \const{SO\_DONTROUTE}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + non invia attraverso un gateway.\\ + \const{SO\_BROADCAST}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& + attiva o disattiva il \textit{broadcast}.\\ + \const{SO\_SNDBUF} &$\bullet$&$\bullet$& &\texttt{int}& + imposta dimensione del buffer di trasmissione.\\ + \const{SO\_RCVBUF} &$\bullet$&$\bullet$& &\texttt{int}& + imposta dimensione del buffer di ricezione.\\ + \const{SO\_LINGER} &$\bullet$&$\bullet$& &\texttt{linger}& + indugia nella chiusura con dati da spedire.\\ + \const{SO\_PRIORITY} &$\bullet$&$\bullet$& &\texttt{int}& + imposta la priorità del socket.\\ + \const{SO\_ERROR} &$\bullet$& & &\texttt{int}& + riceve e cancella gli errori pendenti.\\ + \hline + \end{tabular} + \caption{Le opzioni disponibili al livello \const{SOL\_SOCKET}.} + \label{tab:sock_opt_socklevel} +\end{table} +La tabella elenca le costanti che identificano le singole opzioni da usare +come valore per \param{optname}; le due colonne seguenti indicano per quali +delle due funzioni (\func{getsockopt} o \func{setsockopt}) l'opzione è +disponibile, mentre la colonna successiva indica, quando di ha a che fare con +un valore di \param{optval} intero, se l'opzione è da considerare un numero o +un valore logico. Si è inoltre riportato sulla quinta colonna il tipo di dato +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 senza che non + debba essere effettuato nessun traffico su di essa; in in certi casi 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 non riconosce più la + connessione, ad esempio perché ha avuto un crollo ed è stata + riavviata,\footnote{si ricordi che un normale riavvio non ha questo effetto, + in quanto si passa per la chiusura del processo che invia un segmento FIN + all'altro capo della connessione.} per cui 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 un crash della macchina + all'altro capo 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}. + + + +\item[\const{SO\_OOBINLINE}] se questa opzione viene abilitata i dati + \textit{out-of-band} vengono inviati direttamente nel flusso di dati del + socket (e sono quindi letti con una normale \func{read}) invece che restare + disponibili solo per l'accesso con l'uso del flag \const{MSG\_OOB} di + \func{recvmsg}. Tratteremo l'argomento in dettaglio in + sez.~\ref{sec:TCP_urgent_data}. L'opzione funziona soltanto con socket che + 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 + segnalando ad una \func{select} (vedi sez.~\ref{sec:TCP_sock_select}) che ci + sono dati in ingresso. L'opzione utilizza per \param{optval} un intero che + specifica il numero di byte, ma con Linux questo valore è sempre 1 e non può + 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 + \func{write} di ritornare o segnalando ad una \func{select} (vedi + sez.~\ref{sec:TCP_sock_select}) che è possibile eseguire una scrittura. + L'opzione utilizza per \param{optval} un intero che specifica il numero di + byte, ma con Linux questo valore è 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}) + identica a quella usata con \func{select}. Con \func{getsockopt} si può + leggere il valore attuale, mentre con \func{setsockopt} si imposta il tempo + voluto, usando un valore nullo per \struct{timeval} il timeout viene + rimosso. + + Se l'opzione viene attivata tutte le volte che una delle funzioni di lettura + (\func{read}, \func{readv}, \func{recv}, \func{recvfrom} e \func{recvmsg}) + si blocca in attesa di dati per un tempo maggiore di quello impostato, essa + ritornerà un valore -1 e la variabile \var{errno} sarà impostata con un + errore di \errcode{EAGAIN} e \errcode{EWOULDBLOCK}, così come sarebbe + avvenuto se si fosse aperto il socket in modalità non bloccante. + +\item[\const{SO\_SNDTIMEO}] l'opzione permette di impostare un tempo massimo + sulle operazioni di scrittura su un socket, ed usa gli stessi valori di + \const{SO\_RCVTIMEO}. In questo caso però si avrà un errore di + \errcode{EAGAIN} o \errcode{EWOULDBLOCK} per le funzioni di scrittura + \func{write}, \func{writev}, \func{send}, \func{sendfrom} e \func{sendmsg} + qualora queste restino bloccate per un tempo maggiore di quello specificato. + +\item[\const{SO\_BSDCOMPAT}] questa opzione abilita la compatibilità con il + comportamento di BSD (in particolare ne riproduce i bug). Attualmente è una + opzione usata solo per il protocollo UDP e ne è prevista la rimozione in + futuro. L'opzione utilizza per \param{optval} un intero usato come valore + logico. + + Quando viene abilitata gli errori riportati da messaggi ICMP per un socket + UDP non vengono passati al programma in user space. Con le versioni 2.0.x + del kernel erano anche abilitate altre opzioni per i socket raw, che sono + state rimosse con il passaggio al 2.2; è consigliato correggere i programmi + piuttosto che usare questa funzione. + +\item[\const{SO\_PASSCRED}] questa opzione abilita la ricezione dei messaggi + di controllo \const{SCM\_CREDENTIALS} dei socket unix-domain. Prende per + \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 + unix-domain e può essere usata solo con \func{getsockopt}. Prende come + valore per \param{optval} una apposita struttura \struct{ucred} (vedi + 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. + + Il nome della interfaccia deve essere specificato con una stringa terminata + da uno zero e di lunghezza massima pari a \const{IFNAMSIZ}; l'opzione è + effettiva solo per alcuni tipi di socket, ed in particolare per quelli della + famiglia \const{AF\_INET}; non è invece supportata per i \textit{packet + socket} (vedi sez.~\ref{cha:advanced_socket_xxx}). + + +\item[\const{SO\_DEBUG}] + +\item[\const{SO\_REUSEADDR}] + +\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 valore intero in cui verrà restituto il valore numerico + che lo identifica (ad esempio \const{SOCK\_STREAM}). + +\item[\const{SO\_ACCEPTCONN}] +\item[\const{SO\_DONTROUTE}] +\item[\const{SO\_BROADCAST}] +\item[\const{SO\_SNDBUF}] +\item[\const{SO\_RCVBUF}] +\item[\const{SO\_LINGER}] +\item[\const{SO\_PRIORITY}] +\item[\const{SO\_ERROR}] +\end{basedescript} diff --git a/sources/mygetaddr.c b/sources/mygetaddr.c index b33f9c2..3f51313 100644 --- a/sources/mygetaddr.c +++ b/sources/mygetaddr.c @@ -38,9 +38,9 @@ #include "Gapil.h" /* - * Program myhost + * Program mygetaddr * - * Use gethostbyname and print results + * Use getaddrinfo and print results */ /* Help printing routine */ void usage(void); diff --git a/sources/mygethost.c b/sources/mygethost.c index 76cf844..11ae1ce 100644 --- a/sources/mygethost.c +++ b/sources/mygethost.c @@ -36,7 +36,7 @@ extern int h_errno; #include "Gapil.h" /* - * Program myhost + * Program mygethost * * Use gethostbyname and print results */ @@ -50,6 +50,18 @@ int main(int argc, char *argv[]) */ int i; struct hostent *data; + + struct sock_level { + int level; + char * name; + } sock_level[] = { + SOL_SOCKET, "SOL_SOCKET", + SOL_IP, "SOL_IP", + SOL_TCP, "SOL_TCP", + SOL_IPV6, "SOL_IPV6", + SOL_ICMPV6, "SOL_ICMPV6" + }; + char **alias; char *addr; char buffer[INET6_ADDRSTRLEN]; diff --git a/tcpsock.tex b/tcpsock.tex index ad5e205..b13c16d 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -2581,15 +2581,15 @@ successivo, per tentare di ristabilire la connessione. Il risultato finale qui dipende dall'implementazione dello stack TCP, e nel caso di Linux anche dall'impostazione di alcuni dei parametri di sistema che si trovano in \file{/proc/sys/net/ipv4}, che ne controllano il comportamento: -in questo caso in particolare da \file{tcp\_retries2}. Questo parametro -infatti specifica il numero di volte che deve essere ritentata la -ritrasmissione di un pacchetto nel mezzo di una connessione prima di riportare -un errore di timeout. Il valore preimpostato è pari a 15, il che -comporterebbe 15 tentativi di ritrasmissione, ma nel nostro caso le cose sono -andate diversamente, dato che le ritrasmissioni registrate da \cmd{tcpdump} -sono solo 8; inoltre l'errore riportato all'uscita del client non è stato -\errcode{ETIMEDOUT}, come dovrebbe essere in questo caso, ma -\errcode{EHOSTUNREACH}. +in questo caso in particolare da \file{tcp\_retries2} (vedi +sez.~\ref{sec:sock_sysctl}). Questo parametro infatti specifica il numero di +volte che deve essere ritentata la ritrasmissione di un pacchetto nel mezzo di +una connessione prima di riportare un errore di timeout. Il valore +preimpostato è pari a 15, il che comporterebbe 15 tentativi di ritrasmissione, +ma nel nostro caso le cose sono andate diversamente, dato che le +ritrasmissioni registrate da \cmd{tcpdump} sono solo 8; inoltre l'errore +riportato all'uscita del client non è stato \errcode{ETIMEDOUT}, come dovrebbe +essere in questo caso, ma \errcode{EHOSTUNREACH}. Per capire l'accaduto continuiamo ad analizzare l'output di \cmd{tcpdump}: esso ci mostra che a un certo punto i tentativi di ritrasmissione del @@ -2700,7 +2700,7 @@ riportando appunto come errore \errcode{ECONNRESET}. Occorre precisare che se si vuole che il client sia in grado di accorgersi del crollo del server anche quando non sta effettuando uno scambio di dati, è possibile usare una impostazione speciale del socket (ci torneremo in -sez.~\ref{sec:TCP_sock_options}) che provvede all'esecuzione di questo +sez.~\ref{sec:sock_generic_options}) che provvede all'esecuzione di questo controllo. \section{L'uso dell'I/O multiplexing} @@ -2748,8 +2748,8 @@ pronto per la lettura sono le seguenti: 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 sez.~\ref{sec:TCP_sock_options}); il - suo valore di default è 1 per i socket TCP e UDP. In questo caso una + (tratteremo l'uso di questa opzione in sez.~\ref{sec:sock_generic_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 @@ -2761,7 +2761,7 @@ pronto per la lettura sono le seguenti: \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 sez.~\ref{sec:TCP_sock_options} come sia possibile + valore. Vedremo in sez.~\ref{sec:sock_generic_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 @@ -2782,8 +2782,9 @@ pronto per la scrittura sono le seguenti: 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 + l'opzione del socket \const{SO\_SNDLOWAT} (trattata in + sez.~\ref{sec:sock_generic_options}); 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 @@ -2791,7 +2792,7 @@ pronto per la scrittura sono le seguenti: \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 - sez.~\ref{sec:TCP_sock_options} come sia possibile estrarre e cancellare + sez.~\ref{sec:sock_generic_options} come sia possibile estrarre e cancellare errori pendenti su un socket usando l'opzione \const{SO\_ERROR}. \end{itemize*} -- 2.30.2