Corretti due errori su segnalazione via email
[gapil.git] / tcpsock.tex
index eba896e524bb9979bfc5dd069019a59b06205532..5c618e563e6a3c263323f1fc185aba765a96f58a 100644 (file)
@@ -8,7 +8,7 @@
 %% license is included in the section entitled "GNU Free Documentation
 %% License".
 %%
-\chapter{Socket TCP}
+\chapter{Socket TCP elementari}
 \label{cha:TCP_socket}
 
 In questo capitolo iniziamo ad approfondire la conoscenza dei socket TCP,
@@ -221,7 +221,7 @@ chiusura attiva.  Nella sequenza indicata i dati verrebbero persi, dato che si
 è chiuso il socket dal lato che esegue la chiusura attiva; esistono tuttavia
 situazioni in cui si vuole poter sfruttare questa possibilità, usando una
 procedura che è chiamata \textit{half-close}; torneremo su questo aspetto e su
-come utilizzarlo in \secref{xxx_shutdown}, quando parleremo della funzione
+come utilizzarlo in \secref{sec:TCP_shutdown}, quando parleremo della funzione
 \func{shutdown}.
 
 La emissione del FIN avviene quando il socket viene chiuso, questo però non
@@ -339,8 +339,8 @@ La MSL 
 sulla rete; questo tempo è limitato perché ogni pacchetto IP può essere
 ritrasmesso dai router un numero massimo di volte (detto \textit{hop limit}).
 Il numero di ritrasmissioni consentito è indicato dal campo TTL dell'header di
-IP (per maggiori dettagli vedi \secref{sec:IP_xxx}), e viene decrementato ad
-ogni passaggio da un router; quando si annulla il pacchetto viene scartato.
+IP (per maggiori dettagli vedi \secref{sec:ip_protocol}), e viene decrementato
+ad ogni passaggio da un router; quando si annulla il pacchetto viene scartato.
 Siccome il numero è ad 8 bit il numero massimo di ``\textsl{salti}'' è di 255,
 pertanto anche se il TTL (da \textit{time to live}) non è propriamente un
 limite sul tempo di vita, si stima che un pacchetto IP non possa restare nella
@@ -365,7 +365,7 @@ durata di questo stato.
 
 Il primo dei due motivi precedenti si può capire tornando a
 \figref{fig:TCP_conn_example}: assumendo che l'ultimo ACK della sequenza
-(quello del capo che ha eseguito la chiusura attiva) vanga perso, chi esegue
+(quello del capo che ha eseguito la chiusura attiva) venga perso, chi esegue
 la chiusura passiva non ricevendo risposta rimanderà un ulteriore FIN, per
 questo motivo chi esegue la chiusura attiva deve mantenere lo stato della
 connessione per essere in grado di reinviare l'ACK e chiuderla correttamente.
@@ -635,8 +635,11 @@ precedente in \secref{sec:sock_socket}.
 \subsection{La funzione \func{bind}}
 \label{sec:TCP_func_bind}
 
-La funzione \funcd{bind} assegna un indirizzo locale ad un socket. È usata
-cioè per specificare la prima parte dalla socket pair. Viene usata sul lato
+La funzione \funcd{bind} assegna un indirizzo locale ad un
+socket.\footnote{nel nostro caso la utilizzeremo per socket TCP, ma la
+  funzione è generica e deve essere usata per qualunque tipo di socket
+  \texttt{SOCK\_STREAM} prima che questo possa accettare connessioni.} È usata
+cioè per specificare la prima parte dalla socket pair.  Viene usata sul lato
 server per specificare la porta (e gli eventuali indirizzi locali) su cui poi
 ci si porrà in ascolto. Il prototipo della funzione è il seguente:
 \begin{prototype}{sys/socket.h}
@@ -746,9 +749,17 @@ staticamente a \const{IN6ADRR\_LOOPBACK\_INIT}.
 \label{sec:TCP_func_connect}
 
 La funzione \funcd{connect} è usata da un client TCP per stabilire la
-connessione con un server TCP, il prototipo della funzione è il seguente:
+connessione con un server TCP,\footnote{di nuovo la funzione è generica e
+  supporta vari tipi di socket, la differenza è che per socket senza
+  connessione come quelli di tipo \texttt{SOCK\_DGRAM} la sua chiamata si
+  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:
 \begin{prototype}{sys/socket.h}
-{int connect(int sockfd, const struct sockaddr *servaddr, socklen\_t addrlen)}
+  {int connect(int sockfd, const struct sockaddr *servaddr, socklen\_t
+    addrlen)}
   
   Stabilisce una connessione fra due socket.
   
@@ -848,12 +859,14 @@ necessario effettuare una \func{bind}.
 \label{sec:TCP_func_listen}
 
 La funzione \funcd{listen} serve ad usare un socket in modalità passiva, cioè,
-come dice il nome, per metterlo in ascolto di eventuali connessioni; in
-sostanza l'effetto della funzione è di portare il socket dallo stato
-\texttt{CLOSED} a quello \texttt{LISTEN}. In genere si chiama la funzione in
-un server dopo le chiamate a \func{socket} e \func{bind} e prima della
-chiamata ad \func{accept}. Il prototipo della funzione, come definito dalla
-pagina di manuale, è:
+come dice il nome, per metterlo in ascolto di eventuali
+connessioni;\footnote{questa funzione può essere usata con socket che
+  supportino le connessioni, cioè di tipo \texttt{SOCK\_STREAM} o
+  \texttt{SOCK\_SEQPACKET}.} in sostanza l'effetto della funzione è di portare
+il socket dallo stato \texttt{CLOSED} a quello \texttt{LISTEN}. In genere si
+chiama la funzione in un server dopo le chiamate a \func{socket} e \func{bind}
+e prima della chiamata ad \func{accept}. Il prototipo della funzione, come
+definito dalla pagina di manuale, è:
 \begin{prototype}{sys/socket.h}{int listen(int sockfd, int backlog)}
   Pone un socket in attesa di una connessione.
   
@@ -972,10 +985,13 @@ trasparente dal protocollo TCP.
 \label{sec:TCP_func_accept}
 
 La funzione \funcd{accept} è chiamata da un server per gestire la connessione
-una volta che sia stato completato il \textit{three way handshake}, la
-funzione restituisce un nuovo socket descriptor su cui si potrà operare per
-effettuare la comunicazione. Se non ci sono connessioni completate il processo
-viene messo in attesa. Il prototipo della funzione è il seguente:
+una volta che sia stato completato il \textit{three way
+  handshake},\footnote{la funzione è comunque generica ed è utilizzabile su
+  socket di tipo \texttt{SOCK\_STREAM}, \texttt{SOCK\_SEQPACKET} e
+  \texttt{SOCK\_RDM}.} la funzione restituisce un nuovo socket descriptor su
+cui si potrà operare per effettuare la comunicazione. Se non ci sono
+connessioni completate il processo viene messo in attesa. Il prototipo della
+funzione è il seguente:
 \begin{prototype}{sys/socket.h}
 {int accept(int sockfd, struct sockaddr *addr, socklen\_t *addrlen)} 
  
@@ -1034,8 +1050,8 @@ funzione.  Se non ci sono connessioni pendenti da accettare la funzione mette
 in attesa il processo\footnote{a meno che non si sia impostato il socket per
   essere non bloccante (vedi \secref{sec:file_noblocking}), nel qual caso
   ritorna con l'errore \errcode{EAGAIN}.  Torneremo su questa modalità di
-  operazione in \secref{sec:xxx_sock_noblock}.}  fintanto che non ne arriva
-una.
+  operazione in \secref{sec:TCP_sock_multiplexing}.}  fintanto che non ne
+arriva una.
 
 La funzione può essere usata solo con socket che supportino la connessione
 (cioè di tipo \const{SOCK\_STREAM}, \const{SOCK\_SEQPACKET} o
@@ -1202,7 +1218,7 @@ si aspetta in una qualunque applicazione client/server.
 Per attivare immediatamente l'emissione del FIN e la sequenza di chiusura
 descritta in \secref{sec:TCP_conn_term}, si può invece usare la funzione
 \func{shutdown} su cui torneremo in seguito (vedi
-\secref{sec:TCP_xxx_shutdown}).
+\secref{sec:TCP_shutdown}).
 
 
 
@@ -1514,33 +1530,33 @@ degli altri esempi.
   \label{fig:TCP_daytime_cunc_server_code}
 \end{figure}
 
-Stavolta (\texttt{\small 21--25}) la funzione \func{accept} è chiamata
+Stavolta (\texttt{\small 21--26}) la funzione \func{accept} è chiamata
 fornendo una struttura di indirizzi in cui saranno ritornati l'indirizzo IP e
 la porta da cui il client effettua la connessione, che in un secondo tempo,
-(\texttt{\small 39--43}), se il logging è abilitato, stamperemo sullo standard
+(\texttt{\small 40--44}), se il logging è abilitato, stamperemo sullo standard
 output.
 
 Quando \func{accept} ritorna il server chiama la funzione \func{fork}
-(\texttt{\small 26--30}) per creare il processo figlio che effettuerà
-(\texttt{\small 31--45}) tutte le operazioni relative a quella connessione,
+(\texttt{\small 27--31}) per creare il processo figlio che effettuerà
+(\texttt{\small 32--46}) tutte le operazioni relative a quella connessione,
 mentre il padre proseguirà l'esecuzione del ciclo principale in attesa di
 ulteriori connessioni.
 
 Si noti come il figlio operi solo sul socket connesso, chiudendo
-immediatamente (\texttt{\small 32}) il socket \var{list\_fd}; mentre il padre
-continua ad operare (\texttt{\small 47}) solo sul socket in ascolto chiudendo
-\var{sock\_fd} al ritorno dalla \func{fork}. Per quanto abbiamo detto in
+immediatamente (\texttt{\small 33}) il socket \var{list\_fd}; mentre il padre
+continua ad operare solo sul socket in ascolto chiudendo (\texttt{\small 48})
+\var{conn\_fd} al ritorno dalla \func{fork}. Per quanto abbiamo detto in
 \secref{sec:TCP_func_close} nessuna delle due chiamate a \func{close} causa
 l'innesco della sequenza di chiusura perché il numero di riferimenti al file
 descriptor non si è annullato.
 
 Infatti subito dopo la creazione del socket \var{list\_fd} ha una referenza, e
-lo stesso vale per \var{sock\_fd} dopo il ritorno di \func{accept}, ma dopo la
+lo stesso vale per \var{conn\_fd} dopo il ritorno di \func{accept}, ma dopo la
 \func{fork} i descrittori vengono duplicati nel padre e nel figlio per cui
 entrambi i socket si trovano con due referenze. Questo fa si che quando il
 padre chiude \var{sock\_fd} esso resta con una referenza da parte del figlio,
 e sarà definitivamente chiuso solo quando quest'ultimo, dopo aver completato
-le sue operazioni, chiamerà (\texttt{\small 44}) la funzione \func{close}.
+le sue operazioni, chiamerà (\texttt{\small 45}) la funzione \func{close}.
 
 In realtà per il figlio non sarebbe necessaria nessuna chiamata a
 \func{close}, in quanto con la \func{exit} finale (\texttt{\small 45}) tutti i
@@ -1559,18 +1575,18 @@ per ogni processo) e soprattutto nessuna delle connessioni con i client
 verrebbe chiusa.
 
 Come per ogni server iterativo il lavoro di risposta viene eseguito
-interamente dal processo figlio. Questo si incarica (\texttt{\small 33}) di
+interamente dal processo figlio. Questo si incarica (\texttt{\small 34}) di
 chiamare \func{time} per leggere il tempo corrente, e di stamparlo
-(\texttt{\small 34}) sulla stringa contenuta in \var{buffer} con l'uso di
+(\texttt{\small 35}) sulla stringa contenuta in \var{buffer} con l'uso di
 \func{snprintf} e \func{ctime}. Poi la stringa viene scritta (\texttt{\small
-  35--38}) sul socket, controllando che non ci siano errori. Anche in questo
+  36--39}) sul socket, controllando che non ci siano errori. Anche in questo
 caso si è evitato il ricorso a \func{FullWrite} in quanto la stringa è
 estremamente breve e verrà senz'altro scritta in un singolo segmento.
 
 Inoltre nel caso sia stato abilitato il \textit{logging} delle connessioni, si
-provvede anche (\texttt{\small 39--42}) a stampare sullo standard output
-l'indirizzo e la porta da cui il client ha effettuato la connessione, usando
-valori contenuti nelle strutture restituite da \func{accept}, eseguendo le
+provvede anche (\texttt{\small 40--43}) a stampare sullo standard output
+l'indirizzo e la porta da cui il client ha effettuato la connessione, usando i
+valori contenuti nelle strutture restituite da \func{accept}, eseguendo le
 opportune conversioni con \func{inet\_ntop} e \func{atohs}.
 
 Ancora una volta l'esempio è estremamente semplificato, si noti come di nuovo
@@ -1633,7 +1649,7 @@ compito del client leggere la risposta del server e stamparla sullo standard
 output.
 
 
-\subsection{Il client: prima versione}
+\subsection{Il client \textit{echo}: prima versione}
 \label{sec:TCP_echo_client}
 
 Il codice della prima versione del client per il servizio \textit{echo},
@@ -1694,7 +1710,7 @@ scriverli su \file{stdout}.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15.6cm}
-    \includecodesample{listati/ClientEcho.c}
+    \includecodesample{listati/ClientEcho_first.c}
   \end{minipage} 
   \normalsize
   \caption{Codice della prima versione della funzione \texttt{ClientEcho} per 
@@ -1715,7 +1731,7 @@ programma, usato per
 illustriamo immediatamente.
 
 
-\subsection{Il server: prima versione}
+\subsection{Il server \textit{echo}: prima versione}
 \label{sec:TCPsimp_server_main}
 
 La prima versione del server, contenuta nel file \file{TCP\_echod\_first.c}, è
@@ -1779,15 +1795,15 @@ alla funzione \code{PrintErr}, riportata in \figref{fig:TCP_PrintErr}, al
 posto di \func{perror} per la stampa degli errori. 
 
 Si inizia con il porre (\texttt{\small 37--41}) in ascolto il socket, e poi si
-esegue indefinitamente il ciclo principale (\texttt{\small 42--58}).
-All'interno di questo si ricevono (\texttt{\small 43--46}) le connessioni,
-creando (\texttt{\small 47--50}) un processo figlio per ciascuna di esse.
-Quest'ultimo (\texttt{\small 51--55}), chiuso (\texttt{\small 52}) il
-\textit{listening socket}, esegue (\texttt{\small 53}) la funzione di gestione
-del servizio \code{ServEcho}, ed al ritorno di questa (\texttt{\small 54})
-esce.
-
-Il padre invece si limita (\texttt{\small 56}) a chiudere il \textit{connected
+esegue indefinitamente il ciclo principale (\texttt{\small 42--59}).
+All'interno di questo si ricevono (\texttt{\small 43--47}) le connessioni,
+creando (\texttt{\small 48--51}) un processo figlio per ciascuna di esse.
+Quest'ultimo (\texttt{\small 52--56}), chiuso (\texttt{\small 53}) il
+\textit{listening socket}, esegue (\texttt{\small 54}) la funzione di gestione
+del servizio \code{ServEcho}, ed al ritorno di questa esce (\texttt{\small
+  55}).
+
+Il padre invece si limita (\texttt{\small 57}) a chiudere il \textit{connected
   socket} per ricominciare da capo il ciclo in attesa di nuove connessioni. In
 questo modo si ha un server concorrente. La terminazione del padre non è
 gestita esplicitamente, e deve essere effettuata inviando un segnale al
@@ -2082,8 +2098,8 @@ riscrittura parziale del server, la nuova versione di questo, in cui si sono
 introdotte una serie di nuove opzioni che ci saranno utili per il debug, è
 mostrata in \figref{fig:TCP_echo_server_code_second}, dove si sono riportate
 la sezioni di codice modificate nella seconda versione del programma, il
-sorgente completo di quest'ultimo si trova nel file
-\file{TCP\_echod\_second.c} dei sorgenti allegati alla guida.
+codice completo di quest'ultimo si trova nel file \file{TCP\_echod\_second.c}
+dei sorgenti allegati alla guida.
 
 La prima modifica effettuata è stata quella di introdurre una nuova opzione a
 riga di comando, \texttt{-c}, che permette di richiedere il comportamento
@@ -2143,7 +2159,7 @@ figli stessi e non risentono di \const{SIGCHLD}.
 
 Per questo l'unica modifica sostanziale nel ciclo principale (\texttt{\small
   23--42}), rispetto precedente versione di \figref{fig:TCP_ServEcho_first}, è
-nella sezione (\texttt{\small 26--30}) in cui si effettua la chiamata di
+nella sezione (\texttt{\small 25--31}) in cui si effettua la chiamata di
 \func{accept}.  Quest'ultima viene effettuata (\texttt{\small 26--27})
 all'interno di un ciclo di \code{while}\footnote{la sintassi del C relativa a
   questo ciclo può non essere del tutto chiara. In questo caso infatti si è
@@ -2155,15 +2171,41 @@ altri casi si esce in caso di errore effettivo (\texttt{\small 27--29}),
 altrimenti il programma prosegue.
 
 Si noti che in questa nuova versione si è aggiunta una ulteriore sezione
-(\texttt{\small 31--39}) di aiuto per il debug del programma, che eseguita con
-un controllo (\texttt{\small 31}) sul valore della variabile \var{debugging}
+(\texttt{\small 32--40}) di aiuto per il debug del programma, che eseguita con
+un controllo (\texttt{\small 33}) sul valore della variabile \var{debugging}
 impostato dall'opzione \texttt{-d}. Qualora questo sia nullo, come
-preimpostato, non accade nulla. altrimenti (\texttt{\small 32}) l'indirizzo
+preimpostato, non accade nulla. altrimenti (\texttt{\small 33}) l'indirizzo
 ricevuto da \var{accept} viene convertito in una stringa che poi
-(\texttt{\small 33--38}) viene opportunamente stampata o sullo schermo o nei
+(\texttt{\small 34--39}) viene opportunamente stampata o sullo schermo o nei
 log.
 
+Infine come ulteriore miglioria si è perfezionata la funzione \code{ServEcho},
+sia per tenere conto della nuova funzionalità di debugging, che per effettuare
+un controllo in caso di errore; il codice della nuova versione è mostrato in
+\figref{fig:TCP_ServEcho_second}.
 
+\begin{figure}[!htb] 
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/ServEcho_second.c}
+  \end{minipage} 
+  \normalsize
+  \caption{Codice della seconda versione della funzione \code{ServEcho} per la
+    gestione del servizio \textit{echo}.}
+  \label{fig:TCP_ServEcho_second}
+\end{figure}
+
+Rispetto alla precedente versione di \figref{fig:TCP_ServEcho_first} in questo
+caso si è provveduto a controllare (\texttt{\small 7--10}) il valore di
+ritorno di \func{read} per rilevare un eventuale errore, in modo da stampare
+(\texttt{\small 8}) un messaggio di errore e ritornare (\texttt{\small 9})
+concludendo la connessione.
+
+Inoltre qualora sia stata attivata la funzionalità di debug (avvalorando
+\var{debugging} tramite l'apposita opzione \texttt{-d}) si provvederà a
+stampare (tenendo conto della modalità di invocazione del server, se
+interattiva o in forma di demone) il numero di byte e la stringa letta dal
+client (\texttt{\small 16--24}).
 
 
 \section{I vari scenari critici}
@@ -2237,7 +2279,7 @@ attraverso la sequenza vista in \secref{sec:TCP_conn_term}, per cui la
 al primo accesso al socket. Nel caso di Linux inoltre, anche qualora si
 modifichi il client per fargli gestire l'invio di un segmento di RST alla
 chiusura dal socket (come suggerito da Stevens in \cite{UNP1}), non si ha
-nessun errore al ritorno di \funcd{accept} quanto un errore di
+nessun errore al ritorno di \funcd{accept}, quanto un errore di
 \errcode{ECONNRESET} al primo tentativo di accesso al socket.
 
 
@@ -2384,7 +2426,7 @@ definitiva della connessione anche nel client, dove non comparir
 nell'output di \cmd{netstat}.
 
 Come abbiamo accennato in \secref{sec:TCP_conn_term} e come vedremo più avanti
-in \secref{sec:TCP_xxx_shutdown} la chiusura di un solo capo di un socket è
+in \secref{sec:TCP_shutdown} la chiusura di un solo capo di un socket è
 una operazione lecita, per cui la nostra scrittura avrà comunque successo
 (come si può constatare lanciando usando \cmd{strace}\footnote{il comando
   \cmd{strace} è un comando di debug molto utile che prende come parametro un
@@ -2430,7 +2472,7 @@ la nuova versione della funzione in \figref{fig:TCP_ClientEcho_second}.
   \end{minipage} 
   \normalsize
   \caption{La sezione nel codice della seconda versione della funzione
-    \func{CleintEcho} usata dal client per il servizio \textit{echo}
+    \func{ClientEcho} usata dal client per il servizio \textit{echo}
     modificata per tener conto degli eventuali errori.}
   \label{fig:TCP_ClientEcho_second}
 \end{figure}
@@ -2461,7 +2503,7 @@ avanti, ed 
 fare con la necessità di lavorare con più descrittori, nel qual caso diventa
 si pone la questione di come fare a non restare bloccati su un socket quando
 altri potrebbero essere liberi. Vedremo come affrontare questa problematica in
-\secref{sec:TCP_xxx_advanced}.
+\secref{sec:TCP_sock_multiplexing}.
  
 
 \subsection{Altri scenari di terminazione della connessione}
@@ -2537,7 +2579,7 @@ 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 trovane in \file{/proc/sys/net/ipv4}, che ne controllano il comportamento:
+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
@@ -2573,8 +2615,8 @@ Un altro errore possibile in questo tipo di situazione, che si pu
 quando la macchina è su una rete remota, è \errcode{ENETUNREACH}; esso viene
 riportato alla ricezione di un pacchetto ICMP di \textit{destination
   unreachable} da parte del router che individua l'interruzione della
-connessione. Di nuovo anche qui tutto dipende da chi è il meccanismo più
-veloce ad accorgersi del problema.
+connessione. Di nuovo anche qui il risultato finale dipende da quale è il
+meccanismo più veloce ad accorgersi del problema.
 
 Se però agiamo sui parametri del kernel, e scriviamo in \file{tcp\_retries2}
 un valore di tentativi più basso, possiamo evitare la scadenza della
@@ -2657,7 +2699,8 @@ 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
-\secref{sec:TCP_xxx_sockopt}) che provvede all'esecuzione di questo controllo.
+\secref{sec:TCP_sock_options}) che provvede all'esecuzione di questo
+controllo.