Aggiornate le date nelle note di copyright
[gapil.git] / tcpsock.tex
index cec4ca845ad8e4e0bce5597e13b92c2ed6744120..1a156f7ee2ad13087dd82a7d38286bf138617fd4 100644 (file)
@@ -1,6 +1,6 @@
 %% tcpsock.tex
 %%
-%% Copyright (C) 2000-2004 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2000-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 "Un preambolo",
@@ -34,9 +34,11 @@ questa sezione ci concentreremo sulle modalit
 inizio e conclude una connessione e faremo inoltre un breve accenno al
 significato di alcuni dei vari \textsl{stati} ad essa associati.
 
+
 \subsection{La creazione della connessione: il \textit{three way handshake}}
 \label{sec:TCP_conn_cre}
 
+\index{\textit{three~way~handshake}|(}
 Il processo che porta a creare una connessione TCP è chiamato \textit{three
   way handshake}; la successione tipica degli eventi (e dei
 \textsl{segmenti}\footnote{Si ricordi che il segmento è l'unità elementare di
@@ -116,6 +118,8 @@ aspetta di ricevere con il pacchetto successivo; dato che il primo pacchetto
 SYN consuma un byte, nel \textit{three way handshake} il numero di acknowledge
 è sempre pari al numero di sequenza iniziale incrementato di uno; lo stesso
 varrà anche (vedi fig.~\ref{fig:TCP_close}) per l'acknowledgement di un FIN.
+\index{\textit{three~way~handshake}|)}
+
 
 \subsection{Le opzioni TCP.}
 \label{sec:TCP_TCP_opt}
@@ -705,9 +709,9 @@ Si noti che si 
 \const{INADDR\_ANY}, anche se, essendo questo nullo, il riordinamento è
 inutile.  Si tenga presente comunque che tutte le costanti \val{INADDR\_}
 (riportate in tab.~\ref{tab:TCP_ipv4_addr}) sono definite secondo
-l'\textit{endianess} della macchina, ed anche se esse possono essere
-invarianti rispetto all'ordinamento dei bit, è comunque buona norma usare
-sempre la funzione \func{htonl}.
+l'\textit{endianess}\index{\textit{endianess}} della macchina, ed anche se
+esse possono essere invarianti rispetto all'ordinamento dei bit, è comunque
+buona norma usare sempre la funzione \func{htonl}.
 
 \begin{table}[htb]
   \centering
@@ -754,8 +758,8 @@ connessione con un server TCP,\footnote{di nuovo la funzione 
   limiterà ad impostare l'indirizzo dal quale e verso il quale saranno inviati
   e ricevuti i pacchetti, mentre per socket di tipo \texttt{SOCK\_STREAM} o
   \texttt{SOCK\_SEQPACKET}, essa attiverà la procedura di avvio (nel caso del
-  TCP il \textit{three-way-handsjake}) della connessione.}  il prototipo della
-funzione è il seguente:
+  TCP il \index{\textit{three~way~handshake}}\textit{three way handshake})
+  della connessione.}  il prototipo della funzione è il seguente:
 \begin{prototype}{sys/socket.h}
   {int connect(int sockfd, const struct sockaddr *servaddr, socklen\_t
     addrlen)}
@@ -797,12 +801,12 @@ numero di porta del server a cui ci si vuole connettere, come mostrato
 nell'esempio sez.~\ref{sec:TCP_daytime_client}, usando le funzioni illustrate
 in sez.~\ref{sec:sock_addr_func}.
 
-Nel caso di socket TCP la funzione \func{connect} avvia il \textit{three way
-  handshake}, e ritorna solo quando la connessione è stabilita o si è
-verificato un errore. Le possibili cause di errore sono molteplici (ed i
-relativi codici riportati sopra), quelle che però dipendono dalla situazione
-della rete e non da errori o problemi nella chiamata della funzione sono le
-seguenti:
+Nel caso di socket TCP la funzione \func{connect} avvia il
+\index{\textit{three~way~handshake}}\textit{three way handshake}, e ritorna
+solo quando la connessione è stabilita o si è verificato un errore. Le
+possibili cause di errore sono molteplici (ed i relativi codici riportati
+sopra), quelle che però dipendono dalla situazione della rete e non da errori
+o problemi nella chiamata della funzione sono le seguenti:
 \begin{enumerate}
 \item Il client non riceve risposta al SYN: l'errore restituito è
   \errcode{ETIMEDOUT}. Stevens riporta che BSD invia un primo SYN alla chiamata
@@ -897,11 +901,12 @@ infatti vengono mantenute due code:
 \begin{enumerate}
 \item La coda delle connessioni incomplete (\textit{incomplete connection
     queue} che contiene un riferimento per ciascun socket per il quale è
-  arrivato un SYN ma il \textit{three way handshake} non si è ancora concluso.
-  Questi socket sono tutti nello stato \texttt{SYN\_RECV}.
+  arrivato un SYN ma il \index{\textit{three~way~handshake}}\textit{three way
+    handshake} non si è ancora concluso.  Questi socket sono tutti nello stato
+  \texttt{SYN\_RECV}.
 \item La coda delle connessioni complete (\textit{complete connection queue}
-  che contiene un ingresso per ciascun socket per il quale il three way
-  handshake è stato completato ma ancora \func{accept} non è ritornata.
+  che contiene un ingresso per ciascun socket per il quale il \textit{three
+    way handshake} è stato completato ma ancora \func{accept} non è ritornata.
   Questi socket sono tutti nello stato \texttt{ESTABLISHED}.
 \end{enumerate}
 
@@ -909,12 +914,13 @@ Lo schema di funzionamento 
 quando arriva un SYN da un client il server crea una nuova voce nella coda
 delle connessioni incomplete, e poi risponde con il SYN$+$ACK. La voce resterà
 nella coda delle connessioni incomplete fino al ricevimento dell'ACK dal
-client o fino ad un timeout. Nel caso di completamento del three way handshake
-la voce viene spostata nella coda delle connessioni complete.  Quando il
-processo chiama la funzione \func{accept} (vedi sez.~\ref{sec:TCP_func_accept})
-la prima voce nella coda delle connessioni complete è passata al programma, o,
-se la coda è vuota, il processo viene posto in attesa e risvegliato all'arrivo
-della prima connessione completa.
+client o fino ad un timeout. Nel caso di completamento del
+\index{\textit{three~way~handshake}}\textit{three way handshake} la voce viene
+spostata nella coda delle connessioni complete.  Quando il processo chiama la
+funzione \func{accept} (vedi sez.~\ref{sec:TCP_func_accept}) la prima voce
+nella coda delle connessioni complete è passata al programma, o, se la coda è
+vuota, il processo viene posto in attesa e risvegliato all'arrivo della prima
+connessione completa.
 
 \begin{figure}[htb]
   \centering
@@ -966,7 +972,7 @@ che il compito principale della coda sia quello di gestire il caso in cui il
 server è occupato fra chiamate successive alla \func{accept} (per cui la coda
 più occupata sarebbe quella delle connessioni completate), ma piuttosto quello
 di gestire la presenza di un gran numero di SYN in attesa di concludere il
-three way handshake.
+\textit{three way handshake}\index{\textit{three~way~handshake}}.
 
 Infine va messo in evidenza che, nel caso di socket TCP, quando un SYN arriva
 con tutte le code piene, il pacchetto deve essere ignorato. Questo perché la
@@ -1202,9 +1208,9 @@ argomento per una \func{write} o una \func{read} (anche se l'altro capo della
 connessione non avesse chiuso la sua parte).  Il kernel invierà comunque tutti
 i dati che ha in coda prima di iniziare la sequenza di chiusura.
 
-Vedremo più avanti in sez.~\ref{sec:TCP_so_linger} come è possibile cambiare
-questo comportamento, e cosa deve essere fatto perché il processo possa
-assicurarsi che l'altro capo abbia ricevuto tutti i dati.
+Vedremo più avanti in sez.~\ref{sec:sock_generic_options} come sia possibile
+cambiare questo comportamento, e cosa può essere fatto perché il processo
+possa assicurarsi che l'altro capo abbia ricevuto tutti i dati.
 
 Come per tutti i file descriptor anche per i socket viene mantenuto un numero
 di riferimenti, per cui se più di un processo ha lo stesso socket aperto
@@ -1898,14 +1904,14 @@ connessioni da qualunque indirizzo e da qualunque porta e su qualunque
 interfaccia locale.
 
 A questo punto si può lanciare il client, esso chiamerà \func{socket} e
-\func{connect}; una volta completato il three way handshake la connessione è
-stabilita; la \func{connect} ritornerà nel client\footnote{si noti che è
-  sempre la \func{connect} del client a ritornare per prima, in quanto
-  questo avviene alla ricezione del secondo segmento (l'ACK del server) del
-  three way handshake, la \func{accept} del server ritorna solo dopo
-  un altro mezzo RTT quando il terzo segmento (l'ACK del client) viene
-  ricevuto.} e la \func{accept} nel server, ed usando di nuovo
-\cmd{netstat} otterremmo che:
+\func{connect}; una volta completato il \textit{three way handshake} la
+connessione è stabilita; la \func{connect} ritornerà nel client\footnote{si
+  noti che è sempre la \func{connect} del client a ritornare per prima, in
+  quanto questo avviene alla ricezione del secondo segmento (l'ACK del server)
+  del \textit{three way handshake}, la \func{accept} del server ritorna solo
+  dopo un altro mezzo RTT quando il terzo segmento (l'ACK del client) viene
+  ricevuto.}  e la \func{accept} nel server, ed usando di nuovo \cmd{netstat}
+otterremmo che:
 \begin{verbatim}
 Active Internet connections (servers and established)
 Proto Recv-Q Send-Q Local Address           Foreign Address         State
@@ -2152,7 +2158,7 @@ perch
 interrotta dall'arrivo di \const{SIGCHLD}, è quella ad \func{accept}, che è
 l'unica funzione che può mettere il processo padre in stato di sleep nel
 periodo in cui un figlio può terminare; si noti infatti come le altre
-\index{system call lente} \textit{slow system call}\footnote{si ricordi la
+\index{system~call~lente} \textit{slow system call}\footnote{si ricordi la
   distinzione fatta in sez.~\ref{sec:sig_gen_beha}.} o sono chiamate prima di
 entrare nel ciclo principale, quando ancora non esistono processi figli, o
 sono chiamate dai figli stessi e non risentono di \const{SIGCHLD}.
@@ -2248,13 +2254,14 @@ funzione \func{accept}.
 Benché questo non sia un fatto comune, un evento simile può essere osservato
 con dei server molto occupati. In tal caso, con una struttura del server
 simile a quella del nostro esempio, in cui la gestione delle singole
-connessioni è demandata a processi figli, può accadere che il three way
-handshake venga completato e la relativa connessione abortita subito dopo,
-prima che il padre, per via del carico della macchina, abbia fatto in tempo ad
-eseguire la chiamata ad \func{accept}. Di nuovo si ha una situazione analoga
-a quella illustrata in fig.~\ref{fig:TCP_early_abort}, in cui la connessione
-viene stabilita, ma subito dopo si ha una condizione di errore che la chiude
-prima che essa sia stata accettata dal programma.
+connessioni è demandata a processi figli, può accadere che il \textit{three
+  way handshake}\index{\textit{three~way~handshake}} venga completato e la
+relativa connessione abortita subito dopo, prima che il padre, per via del
+carico della macchina, abbia fatto in tempo ad eseguire la chiamata ad
+\func{accept}. Di nuovo si ha una situazione analoga a quella illustrata in
+fig.~\ref{fig:TCP_early_abort}, in cui la connessione viene stabilita, ma
+subito dopo si ha una condizione di errore che la chiude prima che essa sia
+stata accettata dal programma.
 
 Questo significa che, oltre alla interruzione da parte di un segnale, che
 abbiamo trattato in sez.~\ref{sec:TCP_child_hand} nel caso particolare di
@@ -2357,14 +2364,15 @@ anarres.echo > gont.34559: R 511689732:511689732(0) win 0
 \end{verbatim}
 
 Le prime tre righe vengono prodotte al momento in cui lanciamo il nostro
-client, e corrispondono ai tre pacchetti del three way handshake. L'output del
-comando riporta anche i numeri di sequenza iniziali, mentre la lettera
-\texttt{S} indica che per quel pacchetto si aveva il SYN flag attivo. Si noti
+client, e corrispondono ai tre pacchetti del
+\index{\textit{three~way~handshake}}\textit{three way handshake}.  L'output
+del comando riporta anche i numeri di sequenza iniziali, mentre la lettera
+\texttt{S} indica che per quel pacchetto si aveva il SYN flag attivo.  Si noti
 come a partire dal secondo pacchetto sia sempre attivo il campo \texttt{ack},
 seguito dal numero di sequenza per il quale si da il ricevuto; quest'ultimo, a
 partire dal terzo pacchetto, viene espresso in forma relativa per maggiore
 compattezza.  Il campo \texttt{win} in ogni riga indica la \textit{advertising
-  window} di cui parlavamo in sez.~\ref{sec:TCP_TCP_opt}. Allora si può
+  window} di cui parlavamo in sez.~\ref{sec:TCP_TCP_opt}.  Allora si può
 verificare dall'output del comando come venga appunto realizzata la sequenza
 di pacchetti descritta in sez.~\ref{sec:TCP_conn_cre}: prima viene inviato dal
 client un primo pacchetto con il SYN che inizia la connessione, a cui il
@@ -2372,16 +2380,17 @@ server risponde dando il ricevuto con un secondo pacchetto, che a sua volta
 porta un SYN, cui il client risponde con un il terzo pacchetto di ricevuto.
 
 Ritorniamo allora alla nostra sessione con il servizio echo: dopo le tre righe
-del three way handshake non avremo nulla fin tanto che non scriveremo una
-prima riga sul client; al momento in cui facciamo questo si genera una
-sequenza di altri quattro pacchetti. Il primo, dal client al server,
-contraddistinto da una lettera \texttt{P} che significa che il flag PSH è
-impostato, contiene la nostra riga (che è appunto di 11 caratteri), e ad esso
-il server risponde immediatamente con un pacchetto vuoto di ricevuto. Poi
-tocca al server riscrivere indietro quanto gli è stato inviato, per cui sarà
-lui a mandare indietro un terzo pacchetto con lo stesso contenuto appena
-ricevuto, e a sua volta riceverà dal client un ACK nel quarto pacchetto.
-Questo causerà la ricezione dell'eco nel client che lo stamperà a video.
+del \textit{three way handshake}\index{\textit{three~way~handshake}} non
+avremo nulla fin tanto che non scriveremo una prima riga sul client; al
+momento in cui facciamo questo si genera una sequenza di altri quattro
+pacchetti. Il primo, dal client al server, contraddistinto da una lettera
+\texttt{P} che significa che il flag PSH è impostato, contiene la nostra riga
+(che è appunto di 11 caratteri), e ad esso il server risponde immediatamente
+con un pacchetto vuoto di ricevuto. Poi tocca al server riscrivere indietro
+quanto gli è stato inviato, per cui sarà lui a mandare indietro un terzo
+pacchetto con lo stesso contenuto appena ricevuto, e a sua volta riceverà dal
+client un ACK nel quarto pacchetto.  Questo causerà la ricezione dell'eco nel
+client che lo stamperà a video.
 
 A questo punto noi procediamo ad interrompere l'esecuzione del server con un
 \texttt{C-c} (cioè con l'invio di \const{SIGTERM}): nel momento in cui
@@ -2581,15 +2590,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 +2709,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 +2757,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 +2770,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 +2791,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 +2801,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*}
 
@@ -3400,9 +3410,9 @@ condizioni della rete. Inoltre deve essere specificato come viene classificato
 il traffico nella suddivisione fra dati normali e prioritari. In generale
 pertanto:
 \begin{itemize}
-\item i dati trasmessi su un socket vengono considerati traffico normale,
-  pertanto vengono rilevati da una selezione con \const{POLLIN} o
-  \const{POLLRDNORM}.
+\item i dati inviati su un socket vengono considerati traffico normale,
+  pertanto vengono rilevati alla loro ricezione sull'altro capo da una
+  selezione effettuata con \const{POLLIN} o \const{POLLRDNORM};
 \item i dati \textit{out-of-band} su un socket TCP vengono considerati
   traffico prioritario e vengono rilevati da una condizione \const{POLLIN},
   \const{POLLPRI} o \const{POLLRDBAND}.
@@ -3410,6 +3420,10 @@ pertanto:
   viene considerato traffico normale, pertanto viene rilevato da una
   condizione \const{POLLIN} o \const{POLLRDNORM}, ma una conseguente chiamata
   a \func{read} restituirà 0.
+\item la disponibilità di spazio sul socket per la scrittura di dati viene
+  segnalata con una condizione \const{POLLOUT}.
+\item quando uno dei due capi del socket chiude un suo lato della connessione
+  con \func{shutdown} si riceve una condizione di \const{POLLHUP}.
 \item la presenza di un errore sul socket (sia dovuta ad un segmento RST che a
   timeout) viene considerata traffico normale, ma viene segnalata anche dalla
   condizione \const{POLLERR}.