Indicizzati file sotto /proc, ed ulteriore materiale su ''inotify''.
[gapil.git] / tcpsock.tex
index 7261246389bdf1e8ac4b3f8fb13b51d263fdfa93..485f36f0be956b66ddef6942654ddce9b42dfc35 100644 (file)
@@ -1,6 +1,6 @@
 %% tcpsock.tex
 %%
-%% Copyright (C) 2000-2006 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2000-2007 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",
@@ -8,6 +8,7 @@
 %% license is included in the section entitled "GNU Free Documentation
 %% License".
 %%
+
 \chapter{I socket TCP}
 \label{cha:TCP_socket}
 
@@ -140,7 +141,7 @@ connessione.  Normalmente vengono usate le seguenti opzioni:
   connessione annuncia all'altro il massimo ammontare di dati che vorrebbe
   accettare per ciascun segmento nella connessione corrente. È possibile
   leggere e scrivere questo valore attraverso l'opzione del socket
-  \const{TCP\_MAXSEG} (vedi sez.~\ref{sec:sock_tcp_udp_options}}).
+  \const{TCP\_MAXSEG} (vedi sez.~\ref{sec:sock_tcp_udp_options}).
   
 \item \textit{window scale option}, il protocollo TCP implementa il controllo
   di flusso attraverso una \itindex{advertised~window} \textit{advertised
@@ -153,7 +154,7 @@ connessione.  Normalmente vengono usate le seguenti opzioni:
     lo stack TCP.} ma alcuni tipi di connessione come quelle ad alta velocità
   (sopra i 45Mbit/sec) e quelle che hanno grandi ritardi nel cammino dei
   pacchetti (come i satelliti) richiedono una finestra più grande per poter
-  ottenere il massimo dalla trasmissione, per questo esiste questa opzione che
+  ottenere il massimo dalla trasmissione. Per questo esiste questa opzione che
   indica un fattore di scala da applicare al valore della
   \itindex{advertised~window} finestra annunciata\footnote{essendo una nuova
     opzione per garantire la compatibilità con delle vecchie implementazioni
@@ -162,9 +163,15 @@ connessione.  Normalmente vengono usate le seguenti opzioni:
     inserendola anche lui nel suo SYN di risposta dell'apertura della
     connessione.} per la connessione corrente (espresso come numero di bit cui
   spostare a sinistra il valore della finestra annunciata inserito nel
-  pacchetto). Con Linux è possibile impostare questo valore a livello di
-  sistema con una opportuna \textit{sysctl} (vedi
-  sez.~\ref{sec:sock_ipv4_sysctl}). 
+  pacchetto). Con Linux è possibile indicare al kernel di far negoziare il
+  fattore di scala in fase di creazione di una connessione tramite la
+  \textit{sysctl} \texttt{tcp\_window\_scaling} (vedi
+  sez.~\ref{sec:sock_ipv4_sysctl}).\footnote{per poter usare questa
+    funzionalità è comunque necessario ampliare le dimensioni dei buffer di
+    ricezione e spedizione, cosa che può essere fatta sia a livello di sistema
+    con le opportune \textit{sysctl} (vedi sez.~\ref{sec:sock_ipv4_sysctl}) che
+    a livello di singoli socket con le relative opzioni (vedi
+    sez.~\ref{sec:sock_tcp_udp_options}).}
 
 \item \textit{timestamp option}, è anche questa una nuova opzione necessaria
   per le connessioni ad alta velocità per evitare possibili corruzioni di dati
@@ -298,10 +305,10 @@ che il protocollo viene ad assumere per i due lati, server e client.
   \label{fig:TCP_conn_example}
 \end{figure}
 
-La connessione viene iniziata dal client che annuncia una MSS
-\itindex{Maximum~Segment~Size} di 1460, un valore tipico con Linux per IPv4 su
-Ethernet, il server risponde con lo stesso valore (ma potrebbe essere anche un
-valore diverso).
+La connessione viene iniziata dal client che annuncia una
+\itindex{Maximum~Segment~Size} MSS di 1460, un valore tipico con Linux per
+IPv4 su Ethernet, il server risponde con lo stesso valore (ma potrebbe essere
+anche un valore diverso).
 
 Una volta che la connessione è stabilita il client scrive al server una
 richiesta (che assumiamo stare in un singolo segmento, cioè essere minore dei
@@ -472,11 +479,11 @@ dall'\href{http://www.ietf.org/rfc/rfc1700.txt}{RFC~1700} che contiene
 l'elenco delle porte assegnate dalla IANA (la \textit{Internet Assigned Number
   Authority}) ma l'elenco viene costantemente aggiornato e pubblicato su
 internet (una versione aggiornata si può trovare all'indirizzo
-\href{ftp://ftp.isi.edu/in-notes/iana/assignements/port-number}
-{\texttt{ftp://ftp.isi.edu/in-notes/iana/assignements/port-numbers}}); inoltre
-in un sistema unix-like un analogo elenco viene mantenuto nel file
-\file{/etc/services}, con la corrispondenza fra i vari numeri di porta ed il
-nome simbolico del servizio.  I numeri sono divisi in tre intervalli:
+\href{http://www.iana.org/assignments/port-numbers}
+{\texttt{http://www.iana.org/assignments/port-numbers}}); inoltre in un
+sistema unix-like un analogo elenco viene mantenuto nel file
+\conffile{/etc/services}, con la corrispondenza fra i vari numeri di porta ed
+il nome simbolico del servizio.  I numeri sono divisi in tre intervalli:
 
 \begin{enumerate*}
 \item \textsl{le porte note}. I numeri da 0 a 1023. Queste sono controllate e
@@ -702,7 +709,7 @@ per il server\footnote{un'eccezione a tutto ci
   demone che deve essere contattato dai client per ottenere la porta effimera
   su cui si trova il server.} che in genere viene identificato dalla porta su
 cui risponde (l'elenco di queste porte, e dei relativi servizi, è in
-\file{/etc/services}).
+\conffile{/etc/services}).
 
 Con \func{bind} si può assegnare un indirizzo IP specifico ad un socket,
 purché questo appartenga ad una interfaccia della macchina.  Per un client TCP
@@ -727,9 +734,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}\itindex{endianess} della macchina, ed anche se
-esse possono essere invarianti rispetto all'ordinamento dei bit, è comunque
-buona norma usare sempre la funzione \func{htonl}.
+\itindex{endianess} 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}.
 
 \begin{table}[htb]
   \centering
@@ -776,7 +783,7 @@ 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 \const{SOCK\_STREAM} o
   \const{SOCK\_SEQPACKET}, essa attiverà la procedura di avvio (nel caso del
-  TCP il \itindex{three~way~handshake}\textit{three way handshake}) della
+  TCP il \itindex{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
@@ -821,11 +828,11 @@ 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
-\itindex{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:
+\itindex{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
@@ -835,7 +842,7 @@ o problemi nella chiamata della funzione sono le seguenti:
   secondi per un numero di volte che può essere stabilito dall'utente. Questo
   può essere fatto a livello globale con una opportuna
   \func{sysctl},\footnote{o più semplicemente scrivendo il valore voluto in
-    \file{/proc/sys/net/ipv4/tcp\_syn\_retries}, vedi
+    \procfile{/proc/sys/net/ipv4/tcp\_syn\_retries}, vedi
     sez.~\ref{sec:sock_ipv4_sysctl}.} e a livello di singolo socket con
   l'opzione \const{TCP\_SYNCNT} (vedi sez.~\ref{sec:sock_tcp_udp_options}). Il
   valore predefinito per la ripetizione dell'invio è di 5 volte, che comporta
@@ -970,12 +977,12 @@ indicare la lunghezza della coda delle connessioni complete. La lunghezza
 della coda delle connessioni incomplete può essere ancora controllata usando
 la funzione \func{sysctl} con il parametro \const{NET\_TCP\_MAX\_SYN\_BACKLOG}
 o scrivendola direttamente in
-\file{/proc/sys/net/ipv4/tcp\_max\_syn\_backlog}.  Quando si attiva la
+\procfile{/proc/sys/net/ipv4/tcp\_max\_syn\_backlog}.  Quando si attiva la
 protezione dei syncookies però (con l'opzione da compilare nel kernel e da
-attivare usando \file{/proc/sys/net/ipv4/tcp\_syncookies}) questo valore viene
-ignorato e non esiste più un valore massimo.  In ogni caso in Linux il valore
-di \param{backlog} viene troncato ad un massimo di \const{SOMAXCONN} se è
-superiore a detta costante (che di default vale 128).\footnote{il valore di
+attivare usando \procfile{/proc/sys/net/ipv4/tcp\_syncookies}) questo valore
+viene ignorato e non esiste più un valore massimo.  In ogni caso in Linux il
+valore di \param{backlog} viene troncato ad un massimo di \const{SOMAXCONN} se
+è superiore a detta costante (che di default vale 128).\footnote{il valore di
   questa costante può essere controllato con un altro parametro di
   \func{sysctl}, vedi sez.~\ref{sec:sock_ioctl_IP}.}
 
@@ -2035,7 +2042,7 @@ esaminato in sez.~\ref{sec:proc_termination}). In questo caso avremo l'invio
 del segnale \const{SIGCHLD} al padre, ma dato che non si è installato un
 gestore e che l'azione predefinita per questo segnale è quella di essere
 ignorato, non avendo predisposto la ricezione dello stato di terminazione,
-otterremo che il processo figlio entrerà nello stato di zombie\index{zombie}
+otterremo che il processo figlio entrerà nello stato di \index{zombie} zombie
 (si riveda quanto illustrato in sez.~\ref{sec:sig_sigchld}), come risulterà
 ripetendo il comando \cmd{ps}:
 \begin{verbatim}
@@ -2043,7 +2050,7 @@ ripetendo il comando \cmd{ps}:
  2359 pts/0    Z      0:00 [echod <defunct>]
 \end{verbatim}
 
-Dato che non è il caso di lasciare processi zombie\index{zombie}, occorrerà
+Dato che non è il caso di lasciare processi \index{zombie} zombie, occorrerà
 ricevere opportunamente lo stato di terminazione del processo (si veda
 sez.~\ref{sec:proc_wait}), cosa che faremo utilizzando \const{SIGCHLD} secondo
 quanto illustrato in sez.~\ref{sec:sig_sigchld}. Una prima modifica al nostro
@@ -2405,13 +2412,13 @@ 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 \textit{three way handshake} \itindex{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
+del \itindex{three~way~handshake} \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
@@ -2615,7 +2622,8 @@ 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} (vedi
+in questo caso in particolare da
+\procrelfile{/proc/sys/net/ipv4}{tcp\_retries2} (vedi
 sez.~\ref{sec:sock_ipv4_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
@@ -2737,6 +2745,7 @@ impostazione speciale del socket (ci torneremo in
 sez.~\ref{sec:sock_generic_options}) che provvede all'esecuzione di questo
 controllo.
 
+
 \section{L'uso dell'I/O multiplexing}
 \label{sec:TCP_sock_multiplexing}
 
@@ -2858,9 +2867,8 @@ quando c'
   dati in ricezione; per cui, nella situazione in cui si conosce almeno un
   valore minimo, per evitare la penalizzazione dovuta alla ripetizione delle
   operazioni di lettura per accumulare dati sufficienti, si può lasciare al
-  kernel il compito di impostare un minimo al di sotto del quale il file
-  descriptor, pur avendo disponibili dei dati, non viene dato per pronto in
-  lettura.}
+  kernel il compito di impostare un minimo al di sotto del quale il socket,
+  pur avendo disponibili dei dati, non viene dato per pronto in lettura.}
 
 
 
@@ -3209,8 +3217,8 @@ precedente versione causava l'immediato ritorno della funzione; in questo caso
 prima (\texttt{\small 19}) si imposta opportunamente \var{eof} ad un valore
 non nullo, dopo di che (\texttt{\small 20}) si effettua la chiusura del lato
 in scrittura del socket con \func{shutdown}. Infine (\texttt{\small 21}) si
-usa la macro \macro{FD\_CLR} per togliere lo standard input dal file
-descriptor set. \itindex{file~descriptor~set}
+usa la macro \macro{FD\_CLR} per togliere lo standard input dal
+\itindex{file~descriptor~set} \textit{file descriptor set}.
 
 In questo modo anche se la lettura del file in ingresso è conclusa, la
 funzione non esce dal ciclo principale (\texttt{\small 11--50}), ma continua
@@ -3350,13 +3358,13 @@ vi sono dati sui socket connessi, per questo si ripete un ciclo
 diverso da zero; in questo modo se l'unico socket con attività era quello
 connesso, avendo opportunamente decrementato il contatore, il ciclo verrà
 saltato, e si ritornerà immediatamente (ripetuta l'inizializzazione del
-\itindex{file~descriptor~set} file descriptor set con i nuovi valori nella
-tabella) alla chiamata di \func{accept}. Se il socket attivo non è quello in
-ascolto, o ce ne sono comunque anche altri, il valore di \var{n} non sarà
-nullo ed il controllo sarà eseguito. Prima di entrare nel ciclo comunque si
-inizializza (\texttt{\small 28}) il valore della variabile \var{i} che useremo
-come indice nella tabella \var{fd\_open} al valore minimo, corrispondente al
-file descriptor del socket in ascolto.
+\itindex{file~descriptor~set} \textit{file descriptor set} con i nuovi valori
+nella tabella) alla chiamata di \func{accept}. Se il socket attivo non è
+quello in ascolto, o ce ne sono comunque anche altri, il valore di \var{n} non
+sarà nullo ed il controllo sarà eseguito. Prima di entrare nel ciclo comunque
+si inizializza (\texttt{\small 28}) il valore della variabile \var{i} che
+useremo come indice nella tabella \var{fd\_open} al valore minimo,
+corrispondente al file descriptor del socket in ascolto.
 
 Il primo passo (\texttt{\small 30}) nella verifica è incrementare il valore
 dell'indice \var{i} per posizionarsi sul primo valore possibile per un file
@@ -3569,16 +3577,20 @@ uscita e notifica in caso si errore (\texttt{\small 49--52}).
 Come si può notare la logica del programma è identica a quella vista in
 fig.~\ref{fig:TCP_SelectEchod} per l'analogo server basato su \func{select};
 la sola differenza significativa è che in questo caso non c'è bisogno di
-rigenerare i \itindex{file~descriptor~set} file descriptor set in quanto
-l'uscita è indipendente dai dati in ingresso. Si applicano comunque anche a
-questo server le considerazioni finali di sez.~\ref{sec:TCP_serv_select}.
+rigenerare i \itindex{file~descriptor~set} \textit{file descriptor set} in
+quanto l'uscita è indipendente dai dati in ingresso. Si applicano comunque
+anche a questo server le considerazioni finali di
+sez.~\ref{sec:TCP_serv_select}.
+
+% TODO fare esempio con epoll
+
 
 
 % LocalWords:  socket TCP client dell'I multiplexing stream three way handshake
 % LocalWords:  header stack kernel SYN ACK URG syncronize sez bind listen fig
 % LocalWords:  accept connect active acknowledge l'acknowledge nell'header MSS
 % LocalWords:  sequence number l'acknowledgement dell'header options l'header
-% LocalWords:  option MMS segment size MAXSEG window advertized Mbit sec nell'
+% LocalWords:  option MMS segment size MAXSEG window advertised Mbit sec nell'
 % LocalWords:  timestamp RFC long fat close of l'end l'ACK half shutdown CLOSED
 % LocalWords:  netstat SENT ESTABLISHED WAIT IPv Ethernet piggybacking UDP MSL
 % LocalWords:  l'overhead Stevens Lifetime router hop limit TTL to live RST SSH
@@ -3612,7 +3624,7 @@ questo server le considerazioni finali di sez.~\ref{sec:TCP_serv_select}.
 % LocalWords:  SNDLOWAT third fset maxfd fileno ISSET closed how SHUT RD WR eof
 % LocalWords:  RDWR fifo Trip ping fourth CLR sull'I SETSIZE nread break Denial
 % LocalWords:  Service poll POLLIN POLLRDNORM POLLPRI POLLRDBAND POLLOUT events
-% LocalWords:  POLLHUP POLLERR revents pollfd Di
+% LocalWords:  POLLHUP POLLERR revents pollfd Di scaling SYNCNT DoS
 
 %%% Local Variables: 
 %%% mode: latex