Varie correzioni, completata revisione capitolo sull'I/O su file
[gapil.git] / othersock.tex
index d73aa57b5328364ab5ed84531873f1fb2cccf044..325fb0d02745c2c674e6c05fbb35ca8d840c2ced 100644 (file)
@@ -1,46 +1,47 @@
 %% othersock.tex
 %%
-%% Copyright (C) 2004 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2004-2019 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",
+%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
 %% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
 %% license is included in the section entitled "GNU Free Documentation
 %% License".
 %%
+
 \chapter{Gli altri tipi di socket}
 \label{cha:other_socket}
 
-Dopo aver trattato in cap.~\ref{cha:TCP_socket} i socket TCP, che costituiscono
-l'esempio più comune dell'interfaccia dei socket, esamineremo in questo
-capitolo gli altri tipi di socket, a partire dai socket UDP, e i socket
-\textit{Unix domain} già incontrati in \secref{sec:ipc_socketpair}.
+Dopo aver trattato in cap.~\ref{cha:TCP_socket} i socket TCP, che
+costituiscono l'esempio più comune dell'interfaccia dei socket, esamineremo in
+questo capitolo gli altri tipi di socket, a partire dai socket UDP, e i socket
+\textit{Unix domain} già incontrati in sez.~\ref{sec:ipc_socketpair}.
 
 
 \section{I socket UDP}
 \label{sec:UDP_socket}
 
-Dopo i socket TCP i socket più utilizzati nella programmazione di rete sono i
+Dopo i socket TCP i socket più utilizzati nella programmazione di rete sono i
 socket UDP: protocolli diffusi come NFS o il DNS usano principalmente questo
 tipo di socket. Tratteremo in questa sezione le loro caratteristiche
-principali e le modalità per il loro utilizzo.
+principali e le modalità per il loro utilizzo.
 
 
 \subsection{Le caratteristiche di un socket UDP}
 \label{sec:UDP_characteristics}
 
-Come illustrato in sez.\ref{sec:net_udp} UDP è un protocollo molto semplice che
-non supporta le connessioni e non è affidabile: esso si appoggia direttamente
+Come illustrato in sez.\ref{sec:net_udp} UDP è un protocollo molto semplice che
+non supporta le connessioni e non è affidabile: esso si appoggia direttamente
 sopra IP (per i dettagli sul protocollo si veda sez.~\ref{sec:udp_protocol}).
-I dati vengono inviati in forma di pacchetti, e non ne è assicurata né la
-effettiva ricezione né l'arrivo nell'ordine in cui vengono inviati. Il
-vantaggio del protocollo è la velocità, non è necessario trasmettere le
-informazioni di controllo ed il risultato è una trasmissione di dati più
+I dati vengono inviati in forma di pacchetti, e non ne è assicurata né la
+effettiva ricezione né l'arrivo nell'ordine in cui vengono inviati. Il
+vantaggio del protocollo è la velocità, non è necessario trasmettere le
+informazioni di controllo ed il risultato è una trasmissione di dati più
 veloce ed immediata.
 
 Questo significa che a differenza dei socket TCP i socket UDP non supportano
 una comunicazione di tipo \textit{stream} in cui si ha a disposizione un
-flusso continuo di dati che può essere letto un po' alla volta, ma piuttosto
+flusso continuo di dati che può essere letto un po' alla volta, ma piuttosto
 una comunicazione di tipo \textit{datagram}, in cui i dati arrivano in singoli
 blocchi che devono essere letti integralmente.
 
@@ -51,17 +52,16 @@ essere aperti quando si usa la funzione \func{socket} (si riveda quanto
 illustrato a suo tempo in tab.~\ref{tab:sock_sock_valid_combinations})
 utilizzando per il tipo di socket il valore \const{SOCK\_DGRAM}.
 
-Questa differenza comporta ovviamente che anche le modalità con cui si usano i
+Questa differenza comporta ovviamente che anche le modalità con cui si usano i
 socket UDP sono completamente diverse rispetto ai socket TCP, ed in
 particolare non esistendo il concetto di connessione non esiste il meccanismo
-del \textit{three way handshake} né quello degli stati del protocollo. In
-realtà tutto quello che avviene nella comunicazione attraverso dei socket UDP
-è la trasmissione di un pacchetto da un client ad un server o viceversa,
+del \textit{three way handshake} né quello degli stati del protocollo. In
+realtà tutto quello che avviene nella comunicazione attraverso dei socket UDP
+è la trasmissione di un pacchetto da un client ad un server o viceversa,
 secondo lo schema illustrato in fig.~\ref{fig:UDP_packet-exchange}.
 
-\begin{figure}[htb]
-  \centering
-  \includegraphics[width=10cm]{img/udp_connection}  
+\begin{figure}[!htb]
+  \centering \includegraphics[width=10cm]{img/udp_connection}  
   \caption{Lo schema di interscambio dei pacchetti per una comunicazione via
      UDP.}
   \label{fig:UDP_packet-exchange}
@@ -69,24 +69,24 @@ secondo lo schema illustrato in fig.~\ref{fig:UDP_packet-exchange}.
 
 Come illustrato in fig.~\ref{fig:UDP_packet-exchange} la struttura generica di
 un server UDP prevede, una volta creato il socket, la chiamata a \func{bind}
-per mettersi in ascolto dei dati. Questa è l'unica parte comune con un server
-TCP: non essendovi il concetto di connessione le funzioni \func{listen} ed
+per mettersi in ascolto dei dati, questa è l'unica parte comune con un server
+TCP. Non essendovi il concetto di connessione le funzioni \func{listen} ed
 \func{accept} non sono mai utilizzate nel caso di server UDP. La ricezione dei
 dati dal client avviene attraverso la funzione \func{recvfrom}, mentre una
-eventuale risposta sarà inviata con la funzione \func{sendto}.
+eventuale risposta sarà inviata con la funzione \func{sendto}.
 
-Da parte del client invece, una volta creato il socket non sarà necessario
+Da parte del client invece, una volta creato il socket non sarà necessario
 connettersi con \func{connect} (anche se, come vedremo in
-sez.~\ref{sec:UDP_connect}, è possibile usare questa funzione, con un
-significato comunque diverso) ma si potrà effettuare direttamente una
-richiesta inviando un pacchetto con la funzione \func{sendto} e si potrà
+sez.~\ref{sec:UDP_connect}, è possibile usare questa funzione, con un
+significato comunque diverso) ma si potrà effettuare direttamente una
+richiesta inviando un pacchetto con la funzione \func{sendto} e si potrà
 leggere una eventuale risposta con la funzione \func{recvfrom}.
 
-Anche se UDP è completamente diverso rispetto a TCP resta identica la
-possibilità di gestire più canali di comunicazione fra due macchine
-utilizzando le porte. In questo caso il server dovrà usare comunque la
+Anche se UDP è completamente diverso rispetto a TCP resta identica la
+possibilità di gestire più canali di comunicazione fra due macchine
+utilizzando le porte. In questo caso il server dovrà usare comunque la
 funzione \func{bind} per scegliere la porta su cui ricevere i dati, e come nel
-caso dei socket TCP si potrà usare il comando \cmd{netstat} per
+caso dei socket TCP si potrà usare il comando \cmd{netstat} per
 verificare quali socket sono in ascolto:
 \begin{verbatim}
 [piccardi@gont gapil]# netstat -anu
@@ -101,9 +101,9 @@ in questo caso abbiamo attivi il DNS (sulla porta 53, e sulla 32768 per la
 connessione di controllo del server \cmd{named}) ed un server DHCP (sulla
 porta 67).
 
-Si noti però come in questo caso la colonna che indica lo stato sia vuota. I
+Si noti però come in questo caso la colonna che indica lo stato sia vuota. I
 socket UDP infatti non hanno uno stato. Inoltre anche in presenza di traffico
-non si avranno indicazioni delle connessioni attive, proprio perché questo
+non si avranno indicazioni delle connessioni attive, proprio perché questo
 concetto non esiste per i socket UDP, il kernel si limita infatti a ricevere i
 pacchetti ed inviarli al processo in ascolto sulla porta cui essi sono
 destinati, oppure a scartarli inviando un messaggio \textit{ICMP port
@@ -114,27 +114,37 @@ destinati, oppure a scartarli inviando un messaggio \textit{ICMP port
 \label{sec:UDP_sendto_recvfrom}
 
 Come accennato in sez.~\ref{sec:UDP_characteristics} le due funzioni
-principali usate per la trasmissione di dati attraverso i socket UDP sono
-\func{sendto} e \func{recvfrom}. La necessità di usare queste funzioni è
-dovuta al fatto che non esistendo con UDP il concetto di connessione, non si
-ha neanche a disposizione un \textsl{socket connesso} su cui sia possibile
-usare direttamente \func{read} e \func{write} avendo già stabilito (grazie
-alla chiamata ad \func{accept} che lo associa ad una connessione) quali sono
-sorgente e destinazione dei dati.
+principali usate per la trasmissione di dati attraverso i socket UDP (ed in
+generale per i socket di tipo \textit{datagram}) sono \func{sendto} e
+\func{recvfrom}. La necessità di usare queste funzioni è dovuta al fatto che
+non esistendo con UDP il concetto di connessione, non si può stabilire (come
+avviene con i socket TCP grazie alla chiamata ad \func{accept} che li associa
+ad una connessione) quali sono la sorgente e la destinazione dei dati che
+passano sul socket.\footnote{anche se in alcuni casi, come quello di un client
+  che contatta un server, è possibile connettere il socket (vedi
+  sez.~\ref{sec:UDP_connect}), la necessità di \func{sendto} e \func{recvfrom}
+  resta, dato che questo è possibile solo sul lato del client.}
+
+Per questo anche se in generale si possono comunque leggere i dati con
+\func{read}, usando questa funzione non si sarà in grado di determinare da
+quale fra i possibili corrispondenti (se ve ne sono più di uno, come avviene
+sul lato del server) questi arrivino. E non sarà comunque possibile usare
+\func{write} (che fallisce un errore di \errval{EDESTADDRREQ}) in quanto non
+è determinato la destinazione che i dati avrebbero.
 
 Per questo motivo nel caso di UDP diventa essenziale utilizzare queste due
 funzioni, che sono comunque utilizzabili in generale per la trasmissione di
 dati attraverso qualunque tipo di socket. Esse hanno la caratteristica di
-prevedere tre argomenti aggiuntivi attraverso i quali è possibile specificare
+prevedere tre argomenti aggiuntivi attraverso i quali è possibile specificare
 la destinazione dei dati trasmessi o ottenere l'origine dei dati ricevuti. La
-prima di queste funzioni è \funcd{sendto} ed il suo prototipo\footnote{il
-  prototipo illustrato è quello utilizzato dalle \acr{glibc}, che seguono le
+prima di queste funzioni è \funcd{sendto} ed il suo prototipo\footnote{il
+  prototipo illustrato è quello utilizzato dalla \acr{glibc}, che segue le
   \textit{Single Unix Specification}, l'argomento \param{flags} era di tipo
-  \type{int} nei vari BSD4.*, mentre nelle \acr{libc4} e \acr{libc5} veniva
-  usato un \type{unsigned int}; l'argomento \param{len} era \type{int} nei
-  vari BSD4.* e nelle \acr{libc4}, ma \type{size\_t} nelle \acr{libc5}; infine
-  l'argomento \param{tolen} era \type{int} nei vari BSD4.* nelle \acr{libc4} e
-  nelle \acr{libc5}.} è:
+  \ctyp{int} nei vari BSD4.*, mentre nelle \acr{libc4} e \acr{libc5} veniva
+  usato un \texttt{unsigned int}; l'argomento \param{len} era \ctyp{int} nei
+  vari BSD4.* e nella \acr{libc4}, ma \type{size\_t} nella \acr{libc5}; infine
+  l'argomento \param{tolen} era \ctyp{int} nei vari BSD4.*, nella \acr{libc4} e
+  nella \acr{libc5}.} è:
 \begin{functions}
   \headdecl{sys/types.h}
   \headdecl{sys/socket.h}
@@ -148,29 +158,29 @@ prima di queste funzioni 
     successo e -1 per un errore; nel qual caso \var{errno} viene impostata al
     rispettivo codice di errore:
   \begin{errlist}
-  \item[\errcode{EAGAIN}] il socket è in modalità non bloccante, ma
+  \item[\errcode{EAGAIN}] il socket è in modalità non bloccante, ma
     l'operazione richiede che la funzione si blocchi.
   \item[\errcode{ECONNRESET}] l'altro capo della comunicazione ha resettato la
     connessione.
-  \item[\errcode{EDESTADDRREQ}] il socket non è di tipo connesso, e non si è
+  \item[\errcode{EDESTADDRREQ}] il socket non è di tipo connesso, e non si è
     specificato un indirizzo di destinazione.
-  \item[\errcode{EISCONN}] il socket è già connesso, ma si è specificato un
+  \item[\errcode{EISCONN}] il socket è già connesso, ma si è specificato un
     destinatario.
   \item[\errcode{EMSGSIZE}] il tipo di socket richiede l'invio dei dati in un
     blocco unico, ma la dimensione del messaggio lo rende impossibile.
-  \item[\errcode{ENOBUFS}] la coda di uscita dell'interfaccia è già piena (di
+  \item[\errcode{ENOBUFS}] la coda di uscita dell'interfaccia è già piena (di
     norma Linux non usa questo messaggio ma scarta silenziosamente i
     pacchetti).
-  \item[\errcode{ENOTCONN}] il socket non è connesso e non si è specificata
+  \item[\errcode{ENOTCONN}] il socket non è connesso e non si è specificata
     una destinazione.
-  \item[\errcode{EOPNOTSUPP}] il valore di \param{flag} non è appropriato per
+  \item[\errcode{EOPNOTSUPP}] il valore di \param{flag} non è appropriato per
     il tipo di socket usato.
-  \item[\errcode{EPIPE}] il capo locale della connessione è stato chiuso, si
-    riceverà anche un segnale di \const{SIGPIPE}, a meno di non aver impostato
+  \item[\errcode{EPIPE}] il capo locale della connessione è stato chiuso, si
+    riceverà anche un segnale di \signal{SIGPIPE}, a meno di non aver impostato
     \const{MSG\_NOSIGNAL} in \param{flags}.
   \end{errlist}
   ed anche \errval{EFAULT}, \errval{EBADF}, \errval{EINVAL}, \errval{EINTR},
-  \errval{ENOMEM}, \errval{ENOTSOCK} più gli eventuali altri errori relativi
+  \errval{ENOMEM}, \errval{ENOTSOCK} più gli eventuali altri errori relativi
   ai protocolli utilizzati.}
 \end{functions}
 
@@ -178,12 +188,12 @@ I primi tre argomenti sono identici a quelli della funzione \func{write} e
 specificano il socket \param{sockfd} a cui si fa riferimento, il buffer
 \param{buf} che contiene i dati da inviare e la relativa lunghezza
 \param{len}.  Come per \func{write} la funzione ritorna il numero di byte
-inviati; nel caso di UDP però questo deve sempre corrispondere alla dimensione
+inviati; nel caso di UDP però questo deve sempre corrispondere alla dimensione
 totale specificata da \param{len} in quanto i dati vengono sempre inviati in
 forma di pacchetto e non possono essere spezzati in invii successivi.  Qualora
 non ci sia spazio nel buffer di uscita la funzione si blocca (a meno di non
-avere aperto il socket in modalità non bloccante), se invece non è possibile
-inviare il messaggio all'interno di un unico pacchetto (ad esempio perché
+avere aperto il socket in modalità non bloccante), se invece non è possibile
+inviare il messaggio all'interno di un unico pacchetto (ad esempio perché
 eccede le dimensioni massime del protocollo sottostante utilizzato) essa
 fallisce con l'errore di \errcode{EMSGSIZE}. 
 
@@ -191,38 +201,38 @@ I due argomenti \param{to} e \param{tolen} servono a specificare la
 destinazione del messaggio da inviare, e indicano rispettivamente la struttura
 contenente l'indirizzo di quest'ultima e la sua dimensione; questi argomenti
 vanno specificati stessa forma in cui li si sarebbero usati con
-\func{connect}. Nel nostro caso \param{to} dovrà puntare alla struttura
+\func{connect}. Nel nostro caso \param{to} dovrà puntare alla struttura
 contenente l'indirizzo IP e la porta di destinazione verso cui si vogliono
-inviare i dati (questo è indifferente rispetto all'uso di TCP o UDP, usando
+inviare i dati (questo è indifferente rispetto all'uso di TCP o UDP, usando
 socket diversi si sarebbero dovute utilizzare le rispettive strutture degli
 indirizzi).
 
-Se il socket è di un tipo che prevede le connessioni (ad esempio un socket
-TCP), questo deve essere già connesso prima di poter eseguire la funzione, in
-caso contrario si riceverà un errore di \errcode{ENOTCONN}. In questo
+Se il socket è di un tipo che prevede le connessioni (ad esempio un socket
+TCP), questo deve essere già connesso prima di poter eseguire la funzione, in
+caso contrario si riceverà un errore di \errcode{ENOTCONN}. In questo
 specifico caso in cui gli argomenti \param{to} e \param{tolen} non servono
-essi dovranno essere inizializzati rispettivamente a \const{NULL} e 0;
+essi dovranno essere inizializzati rispettivamente a \val{NULL} e 0;
 normalmente quando si opera su un socket connesso essi vengono ignorati, ma
-qualora si sia specificato un indirizzo è possibile ricevere un errore di
+qualora si sia specificato un indirizzo è possibile ricevere un errore di
 \errcode{EISCONN}.
 
-Finora abbiamo tralasciato l'argomento \param{flags}; questo è un intero usato
-come maschera binaria che permette di impostare una serie di modalità di
+Finora abbiamo tralasciato l'argomento \param{flags}; questo è un intero usato
+come maschera binaria che permette di impostare una serie di modalità di
 funzionamento della comunicazione attraverso il socket (come
-\const{MSG\_NOSIGNAL} che impedisce l'invio del segnale \const{SIGPIPE} quando
-si è già chiuso il capo locale della connessione). Torneremo con maggiori
-dettagli sul significato di questo argomento in sez.~\ref{sec:xxx_sendmsg},
-dove tratteremo le funzioni avanzate dei socket, per il momento ci si può
-limitare ad usare sempre un valore nullo.
+\constd{MSG\_NOSIGNAL} che impedisce l'invio del segnale \signal{SIGPIPE}
+quando si è già chiuso il capo locale della connessione). Torneremo con
+maggiori dettagli sul significato di questo argomento in
+sez.~\ref{sec:net_sendmsg}, dove tratteremo le funzioni avanzate dei socket,
+per il momento ci si può limitare ad usare sempre un valore nullo.
 
-La seconda funzione utilizzata nella comunicazione fra socket UDP è
+La seconda funzione utilizzata nella comunicazione fra socket UDP è
 \funcd{recvfrom}, che serve a ricevere i dati inviati da un altro socket; il
-suo prototipo\footnote{il prototipo è quello delle \acr{glibc} che seguono le
-  \textit{Single Unix Specification}, i vari BSD4.*, le \acr{libc4} e le
-  \acr{libc5} usano un \type{int} come valore di ritorno; per gli argomenti
+suo prototipo\footnote{il prototipo è quello della \acr{glibc} che segue le
+  \textit{Single Unix Specification}, i vari BSD4.*, le \acr{libc4} e la
+  \acr{libc5} usano un \ctyp{int} come valore di ritorno; per gli argomenti
   \param{flags} e \param{len} vale quanto detto a proposito di \func{sendto};
-  infine l'argomento \param{fromlen} è \type{int} per i vari BSD4.*, le
-  \acr{libc4} e le \acr{libc5}.} è:
+  infine l'argomento \param{fromlen} è \ctyp{int} per i vari BSD4.*, la
+  \acr{libc4} e la \acr{libc5}.} è:
 \begin{functions}
   \headdecl{sys/types.h}
   \headdecl{sys/socket.h}
@@ -230,22 +240,22 @@ suo prototipo\footnote{il prototipo 
   \funcdecl{ssize\_t recvfrom(int sockfd, const void *buf, size\_t len, int
     flags, const struct sockaddr *from, socklen\_t *fromlen)}
   
-  Riceve un messaggio ad un socket.
+  Riceve un messaggio da un socket.
   
   \bodydesc{La funzione restituisce il numero di byte ricevuti in caso di
-    successo e -1 in caso di errore; nel qual caso \var{errno} assumerà il
+    successo e -1 in caso di errore; nel qual caso \var{errno} assumerà il
     valore:
   \begin{errlist}
-  \item[\errcode{EAGAIN}] il socket è in modalità non bloccante, ma
-    l'operazione richiede che la funzione si blocchi, oppure si è impostato un
-    timeout in ricezione e questo è scaduto.
+  \item[\errcode{EAGAIN}] il socket è in modalità non bloccante, ma
+    l'operazione richiede che la funzione si blocchi, oppure si è impostato un
+    timeout in ricezione e questo è scaduto.
   \item[\errcode{ECONNREFUSED}] l'altro capo della comunicazione ha rifiutato
-    la connessione (in genere perché il relativo servizio non è disponibile).
-  \item[\errcode{ENOTCONN}] il socket è di tipo connesso, ma non si è eseguita
+    la connessione (in genere perché il relativo servizio non è disponibile).
+  \item[\errcode{ENOTCONN}] il socket è di tipo connesso, ma non si è eseguita
     la connessione.
   \end{errlist}
   ed anche \errval{EFAULT}, \errval{EBADF}, \errval{EINVAL}, \errval{EINTR},
-  \errval{ENOMEM}, \errval{ENOTSOCK} più gli eventuali altri errori relativi
+  \errval{ENOMEM}, \errval{ENOTSOCK} più gli eventuali altri errori relativi
   ai protocolli utilizzati.}
 \end{functions}
 
@@ -255,28 +265,40 @@ buffer \param{buf}. A seconda del tipo di socket (se di tipo \textit{datagram}
 o di tipo \textit{stream}) i byte in eccesso che non sono stati letti possono
 rispettivamente andare persi o restare disponibili per una lettura successiva.
 Se non sono disponibili dati la funzione si blocca, a meno di non aver aperto
-il socket in modalità non bloccante, nel qual caso si avrà il solito errore di
+il socket in modalità non bloccante, nel qual caso si avrà il solito errore di
 \errcode{EAGAIN}.  Qualora \param{len} ecceda la dimensione del pacchetto la
-funzione legge comunque i dati disponibili, ed il suo valore di ritorno è
+funzione legge comunque i dati disponibili, ed il suo valore di ritorno è
 comunque il numero di byte letti.
 
 I due argomenti \param{from} e \param{fromlen} sono utilizzati per ottenere
-l'indirizzo del mittente del pacchetto che è stato ricevuto, e devono essere
-opportunamente inizializzati con i puntatori alle variabili dove la struttura
-contenente quest'ultimo e la relativa lunghezza saranno scritti (si noti che
-\param{fromlen} è un valore intero ottenuto come \textit{value return
-  argument}).  Se non si è interessati a questa informazione, entrambi gli
-argomenti devono essere inizializzati al valore \const{NULL}.
+l'indirizzo del mittente del pacchetto che è stato ricevuto, e devono essere
+opportunamente inizializzati; il primo deve contenere il puntatore alla
+struttura (di tipo \ctyp{sockaddr}) che conterrà l'indirizzo e il secondo il
+puntatore alla variabile con la dimensione di detta struttura. Si tenga
+presente che mentre il contenuto della struttura \ctyp{sockaddr} cui punta
+\param{from} può essere qualunque, la variabile puntata da \param{fromlen}
+deve essere opportunamente inizializzata a \code{sizeof(sockaddr)},
+assicurandosi che la dimensione sia sufficiente a contenere tutti i dati
+dell'indirizzo.\footnote{si ricordi che \ctyp{sockaddr} è un tipo generico che
+  serve ad indicare la struttura corrispondente allo specifico tipo di
+  indirizzo richiesto, il valore di \param{fromlen} pone un limite alla
+  quantità di dati che verranno scritti sulla struttura puntata da
+  \param{from} e se è insufficiente l'indirizzo risulterà corrotto.}  Al
+ritorno della funzione si otterranno i dati dell'indirizzo e la sua effettiva
+lunghezza, (si noti che \param{fromlen} è un valore intero ottenuto come
+\textit{value result argument}).  Se non si è interessati a questa
+informazione, entrambi gli argomenti devono essere inizializzati al valore
+\val{NULL}.
 
 Una differenza fondamentale del comportamento di queste funzioni rispetto alle
-usuali \func{read} e \func{write} che abbiamo usato con i socket TCP è che in
-questo caso è perfettamente legale inviare con \func{sendto} un pacchetto
-vuoto (che nel caso conterrà solo le intestazioni di IP e di UDP),
-specificando un valore nullo per \param{len}. Allo stesso modo è possibile
+usuali \func{read} e \func{write} che abbiamo usato con i socket TCP è che in
+questo caso è perfettamente legale inviare con \func{sendto} un pacchetto
+vuoto (che nel caso conterrà solo le intestazioni di IP e di UDP),
+specificando un valore nullo per \param{len}. Allo stesso modo è possibile
 ricevere con \func{recvfrom} un valore di ritorno di 0 byte, senza che questo
 possa configurarsi come una chiusura della connessione\footnote{dato che la
   connessione non esiste, non ha senso parlare di chiusura della connessione,
-  questo significa anche che con i socket UDP non è necessario usare
+  questo significa anche che con i socket UDP non è necessario usare
   \func{close} o \func{shutdown} per terminare la comunicazione.} o come una
 cessazione delle comunicazioni.
 
@@ -288,14 +310,14 @@ cessazione delle comunicazioni.
 Vediamo allora come implementare un primo client elementare con dei socket
 UDP.  Ricalcando quanto fatto nel caso dei socket TCP prenderemo come primo
 esempio l'uso del servizio \textit{daytime}, utilizzando questa volta UDP. Il
-servizio è definito nell'\href{http://www.ietf.org/rfc/rfc0862.txt}{RFC~867},
+servizio è definito nell'\href{http://www.ietf.org/rfc/rfc0862.txt}{RFC~867},
 che nel caso di uso di UDP prescrive che il client debba inviare un pacchetto
-UDP al server (di contenuto non specificato), il quale risponderà a inviando a
+UDP al server (di contenuto non specificato), il quale risponderà a inviando a
 sua volta un pacchetto UDP contenente la data.
 
-\begin{figure}[!htb] 
+\begin{figure}[!htbp
   \footnotesize \centering
-  \begin{minipage}[c]{15.6cm}
+  \begin{minipage}[c]{\codesamplewidth}
     \includecodesample{listati/UDP_daytime.c}
   \end{minipage} 
   \normalsize
@@ -304,10 +326,10 @@ sua volta un pacchetto UDP contenente la data.
   \label{fig:UDP_daytime_client}
 \end{figure}
 
-In fig.~\ref{fig:UDP_daytime_client} è riportato la sezione principale del
+In fig.~\ref{fig:UDP_daytime_client} è riportato la sezione principale del
 codice del nostro client, il sorgente completo si trova nel file
 \file{UDP\_daytime.c} distribuito con gli esempi allegati alla guida; al
-solito si è tralasciato di riportare in figura la sezione relativa alla
+solito si è tralasciato di riportare in figura la sezione relativa alla
 gestione delle opzioni a riga di comando (nel caso praticamente assenti).
 
 Il programma inizia (\texttt{\small 9--12}) con la creazione del socket, al
@@ -317,33 +339,33 @@ fig.~\ref{fig:TCP_daytime_client_code} si sia usato per il tipo di socket il
 valore \const{SOCK\_DGRAM}, pur mantenendosi nella stessa famiglia data da
 \const{AF\_INET}.
 
-Il passo successivo (\texttt{\small 13--21}) è l'inizializzazione della
+Il passo successivo (\texttt{\small 13--21}) è l'inizializzazione della
 struttura degli indirizzi; prima (\texttt{\small 14}) si cancella
 completamente la stessa con \func{memset}, (\texttt{\small 15}) poi si imposta
 la famiglia dell'indirizzo ed infine (\texttt{\small 16} la porta. Infine
-(\texttt{\small 18--21}) si ricava l'indirizzo del server da contattare dal
-parametro passato a riga di comando, convertendolo con \func{inet\_pton}. Si
-noti come questa sezione sia identica a quella del client TCP di
+(\texttt{\small 18--21}) si ricava l'indirizzo del server da contattare
+dall'argomento passato a riga di comando, convertendolo con \func{inet\_pton}.
+Si noti come questa sezione sia identica a quella del client TCP di
 fig.~\ref{fig:TCP_daytime_client_code}, in quanto la determinazione dell'uso
-di UDP al posto di TCP è stata effettuata quando si è creato il socket.
+di UDP al posto di TCP è stata effettuata quando si è creato il socket.
 
 Una volta completate le inizializzazioni inizia il corpo principale del
-programma, il primo passo è inviare, come richiesto dal protocollo, un
+programma, il primo passo è inviare, come richiesto dal protocollo, un
 pacchetto al server. Questo lo si fa (\texttt{\small 16}) inviando un
 pacchetto vuoto (si ricordi quanto detto in
 sez.~\ref{sec:UDP_sendto_recvfrom}) con \func{sendto}, avendo cura di passare
 un valore nullo per il puntatore al buffer e la lunghezza del messaggio. In
-realtà il protocollo non richiede che il pacchetto sia vuoto, ma dato che il
-server comunque ne ignorerà il contenuto, è inutile inviare dei dati.
+realtà il protocollo non richiede che il pacchetto sia vuoto, ma dato che il
+server comunque ne ignorerà il contenuto, è inutile inviare dei dati.
 
 Verificato (\texttt{\small 24--27}) che non ci siano stati errori nell'invio
 si provvede (\texttt{\small 28}) ad invocare \func{recvfrom} per ricevere la
 risposta del server. Si controlla poi (\texttt{\small 29--32}) che non vi
 siano stati errori in ricezione (uscendo con un messaggio in caso contrario);
-se è tutto a posto la variabile \var{nread} conterrà la dimensione del
-messaggio di risposta inviato dal server che è stato memorizzato su
-\var{buffer}, se (\texttt{\small 34}) pertanto il valore è positivo si
-provvederà (\texttt{\small 35}) a terminare la stringa contenuta nel buffer di
+se è tutto a posto la variabile \var{nread} conterrà la dimensione del
+messaggio di risposta inviato dal server che è stato memorizzato su
+\var{buffer}, se (\texttt{\small 34}) pertanto il valore è positivo si
+provvederà (\texttt{\small 35}) a terminare la stringa contenuta nel buffer di
 lettura\footnote{si ricordi che, come illustrato in
   sez.~\ref{sec:TCP_daytime_client}, il server invia in risposta una stringa
   contenente la data, terminata dai due caratteri CR e LF, che pertanto prima
@@ -352,8 +374,8 @@ stamparla (\texttt{\small 36}) sullo standard output, controllando anche in
 questo caso (\texttt{\small 36--38}) l'esito dell'operazione, ed uscendo con
 un messaggio in caso di errore.
 
-Se pertanto si è avuto cura di attivare il server del servizio
-\textit{daytime}\footnote{di norma questo è un servizio standard fornito dal
+Se pertanto si è avuto cura di attivare il server del servizio
+\textit{daytime}\footnote{di norma questo è un servizio standard fornito dal
   \textsl{superdemone} \cmd{inetd}, per cui basta abilitarlo nel file di
   configurazione di quest'ultimo, avendo cura di predisporre il servizio su
   UDP.} potremo verificare il funzionamento del nostro client interrogando
@@ -372,15 +394,15 @@ tcpdump: listening on lo
 23:41:21.645710 localhost.daytime > localhost.32780: udp 26 (DF)
 \end{verbatim}
 
-Una differenza fondamentale del nostro client è che in questo caso, non
-disponendo di una connessione, è per lui impossibile riconoscere errori di
+Una differenza fondamentale del nostro client è che in questo caso, non
+disponendo di una connessione, è per lui impossibile riconoscere errori di
 invio relativi alla rete. La funzione \func{sendto} infatti riporta solo
 errori locali, i dati vengono comunque scritti e la funzione ritorna senza
-errori anche se il server non è raggiungibile o non esiste un server in
+errori anche se il server non è raggiungibile o non esiste un server in
 ascolto sull'indirizzo di destinazione. Questo comporta ad esempio che se si
-usa il nostro programma interrogando un server inesistente questo resterà
+usa il nostro programma interrogando un server inesistente questo resterà
 perennemente bloccato nella chiamata a \func{recvfrom}, fin quando non lo
-interromperemo. Vedremo in sez.~\ref{sec:UDP_connect} come si può porre rimedio
+interromperemo. Vedremo in sez.~\ref{sec:UDP_connect} come si può porre rimedio
 a questa problematica.
 
 
@@ -389,13 +411,13 @@ a questa problematica.
 
 Nella sezione precedente abbiamo visto come scrivere un client elementare per
 servizio \textit{daytime}, vediamo in questa come deve essere scritto un
-server.  Si ricordi che il compito di quest'ultimo è quello di ricevere un
+server.  Si ricordi che il compito di quest'ultimo è quello di ricevere un
 pacchetto di richiesta ed inviare in risposta un pacchetto contenente una
 stringa con la data corrente. 
 
-\begin{figure}[!htb] 
+\begin{figure}[!htbp
   \footnotesize \centering
-  \begin{minipage}[c]{15.6cm}
+  \begin{minipage}[c]{\codesamplewidth}
     \includecodesample{listati/UDP_daytimed.c}
   \end{minipage} 
   \normalsize
@@ -404,75 +426,75 @@ stringa con la data corrente.
   \label{fig:UDP_daytime_server}
 \end{figure}
 
-In fig.~\ref{fig:UDP_daytime_server} è riportato la sezione principale del
+In fig.~\ref{fig:UDP_daytime_server} è riportato la sezione principale del
 codice del nostro client, il sorgente completo si trova nel file
 \file{UDP\_daytimed.c} distribuito con gli esempi allegati alla guida; anche
-in questo caso si è omessa la sezione relativa alla gestione delle opzioni a
-riga di comando (la sola presente è \texttt{-v} che permette di stampare a
+in questo caso si è omessa la sezione relativa alla gestione delle opzioni a
+riga di comando (la sola presente è \texttt{-v} che permette di stampare a
 video l'indirizzo associato ad ogni richiesta).
 
-Anche in questo caso la prima parte del server (\texttt{\small 9--23}) è
+Anche in questo caso la prima parte del server (\texttt{\small 9--23}) è
 sostanzialmente identica a quella dell'analogo server per TCP illustrato in
 fig.~\ref{fig:TCP_daytime_cunc_server_code}; si inizia (\texttt{\small 10})
 con il creare il socket, uscendo con un messaggio in caso di errore
 (\texttt{\small 10--13}), e di nuovo la sola differenza con il caso precedente
-è il diverso tipo di socket utilizzato. Dopo di che (\texttt{\small 14--18})
-si inizializza la struttura degli indirizzi che poi (\texttt{\small 20}) verrà
+è il diverso tipo di socket utilizzato. Dopo di che (\texttt{\small 14--18})
+si inizializza la struttura degli indirizzi che poi (\texttt{\small 20}) verrà
 usata da \func{bind}; si cancella (\texttt{\small 15}) preventivamente il
 contenuto, si imposta (\texttt{\small 16}) la famiglia dell'indirizzo, la
 porta (\texttt{\small 17}) e l'indirizzo (\texttt{\small 18}) su cui si
 riceveranno i pacchetti.  Si noti come in quest'ultimo sia l'indirizzo
 generico \const{INADDR\_ANY}; questo significa (si ricordi quanto illustrato
-in sez.~\ref{sec:TCP_func_bind}) che il server accetterà pacchetti su uno
+in sez.~\ref{sec:TCP_func_bind}) che il server accetterà pacchetti su uno
 qualunque degli indirizzi presenti sulle interfacce di rete della macchina.
 
-Completata l'inizializzazione tutto quello che resta da fare è eseguire
+Completata l'inizializzazione tutto quello che resta da fare è eseguire
 (\texttt{\small 20--23}) la chiamata a \func{bind}, controllando la presenza
 di eventuali errori, ed uscendo con un avviso qualora questo fosse il caso.
-Nel caso di socket UDP questo è tutto quello che serve per consentire al
-server di ricevere i pacchetti a lui indirizzati, e non è più necessario
+Nel caso di socket UDP questo è tutto quello che serve per consentire al
+server di ricevere i pacchetti a lui indirizzati, e non è più necessario
 chiamare successivamente \func{listen}. In questo caso infatti non esiste il
 concetto di connessione, e quindi non deve essere predisposta una coda delle
 connessioni entranti. Nel caso di UDP i pacchetti arrivano al kernel con un
 certo indirizzo ed una certa porta di destinazione, il kernel controlla se
-corrispondono ad un socket che è stato \textsl{legato} ad essi con
-\func{bind}, qualora questo sia il caso scriverà il contenuto all'interno del
-socket, così che il programma possa leggerlo, altrimenti risponderà alla
+corrispondono ad un socket che è stato \textsl{legato} ad essi con
+\func{bind}, qualora questo sia il caso scriverà il contenuto all'interno del
+socket, così che il programma possa leggerlo, altrimenti risponderà alla
 macchina che ha inviato il pacchetto con un messaggio ICMP di tipo
 \textit{port unreachable}.
 
 Una volta completata la fase di inizializzazione inizia il corpo principale
 (\texttt{\small 24--44}) del server, mantenuto all'interno di un ciclo
 infinito in cui si trattano le richieste. Il ciclo inizia (\texttt{\small 26})
-con una chiamata a \func{recvfrom}, che si bloccherà in attesa di pacchetti
-inviati dai client. Lo scopo della funzione è quello di ritornare tutte le
+con una chiamata a \func{recvfrom}, che si bloccherà in attesa di pacchetti
+inviati dai client. Lo scopo della funzione è quello di ritornare tutte le
 volte che un pacchetto viene inviato al server, in modo da poter ricavare da
 esso l'indirizzo del client a cui inviare la risposta in \var{addr}. Per
 questo motivo in questo caso (al contrario di quanto fatto in
-fig.~\ref{fig:UDP_daytime_client}) si è avuto cura di passare gli argomenti
+fig.~\ref{fig:UDP_daytime_client}) si è avuto cura di passare gli argomenti
 \var{addr} e \var{len} alla funzione.  Dopo aver controllato (\texttt{\small
   27--30}) la presenza di eventuali errori (uscendo con un messaggio di errore
-qualora ve ne siano) si verifica (\texttt{\small 31}) se è stata attivata
+qualora ve ne siano) si verifica (\texttt{\small 31}) se è stata attivata
 l'opzione \texttt{-v} (che imposta la variabile \var{verbose}) stampando nel
-caso (\texttt{\small 32--35}) l'indirizzo da cui si è appena ricevuto una
-richiesta (questa sezione è identica a quella del server TCP illustrato in
+caso (\texttt{\small 32--35}) l'indirizzo da cui si è appena ricevuto una
+richiesta (questa sezione è identica a quella del server TCP illustrato in
 fig.~\ref{fig:TCP_daytime_cunc_server_code}).
 
 Una volta ricevuta la richiesta resta solo da ottenere il tempo corrente
 (\texttt{\small 36}) e costruire (\texttt{\small 37}) la stringa di risposta,
-che poi verrà inviata (\texttt{\small 38}) al client usando \func{sendto},
+che poi verrà inviata (\texttt{\small 38}) al client usando \func{sendto},
 avendo al solito cura di controllare (\texttt{\small 40--42}) lo stato di
 uscita della funzione e trattando opportunamente la condizione di errore.
 
-Si noti come per le peculiarità del protocollo si sia utilizzato un server
+Si noti come per le peculiarità del protocollo si sia utilizzato un server
 iterativo, che processa le richieste una alla volta via via che gli arrivano.
-Questa è una caratteristica comune dei server UDP, conseguenza diretta del
-fatto che non esiste il concetto di connessione, per cui non c'è la necessità
-di trattare separatamente le singole connessioni. Questo significa anche che è
-il kernel a gestire la possibilità di richieste multiple in contemporanea;
-quello che succede è semplicemente che il kernel accumula in un buffer in
+Questa è una caratteristica comune dei server UDP, conseguenza diretta del
+fatto che non esiste il concetto di connessione, per cui non c'è la necessità
+di trattare separatamente le singole connessioni. Questo significa anche che è
+il kernel a gestire la possibilità di richieste multiple in contemporanea;
+quello che succede è semplicemente che il kernel accumula in un buffer in
 ingresso i pacchetti UDP che arrivano e li restituisce al processo uno alla
-volta per ciascuna chiamata di \func{recvfrom}; nel nostro caso sarà poi
+volta per ciascuna chiamata di \func{recvfrom}; nel nostro caso sarà poi
 compito del server distribuire le risposte sulla base dell'indirizzo da cui
 provengono le richieste.
 
@@ -481,23 +503,23 @@ provengono le richieste.
 \label{sec:UDP_problems}
 
 L'esempio del servizio \textit{daytime} illustrato nelle precedenti sezioni
-è in realtà piuttosto particolare, e non evidenzia quali possono essere i
-problemi collegati alla mancanza di affidabilità e all'assenza del concetto di
+è in realtà piuttosto particolare, e non evidenzia quali possono essere i
+problemi collegati alla mancanza di affidabilità e all'assenza del concetto di
 connessione che sono tipiche dei socket UDP. In tal caso infatti il protocollo
-è estremamente semplice, dato che la comunicazione consiste sempre in una
+è estremamente semplice, dato che la comunicazione consiste sempre in una
 richiesta seguita da una risposta, per uno scambio di dati effettuabile con un
-singolo pacchetto, per cui tutti gli eventuali problemi sarebbero assai più
+singolo pacchetto, per cui tutti gli eventuali problemi sarebbero assai più
 complessi da rilevare.
 
-Anche qui però possiamo notare che se il pacchetto di richiesta del client, o
-la risposta del server si perdono, il client resterà permanentemente bloccato
+Anche qui però possiamo notare che se il pacchetto di richiesta del client, o
+la risposta del server si perdono, il client resterà permanentemente bloccato
 nella chiamata a \func{recvfrom}. Per evidenziare meglio quali problemi si
-possono avere proviamo allora con un servizio leggermente più complesso come
+possono avere proviamo allora con un servizio leggermente più complesso come
 \textit{echo}. 
 
-\begin{figure}[!htb] 
+\begin{figure}[!htbp
   \footnotesize \centering
-  \begin{minipage}[c]{15.6cm}
+  \begin{minipage}[c]{\codesamplewidth}
     \includecodesample{listati/UDP_echo_first.c}
   \end{minipage} 
   \normalsize
@@ -506,20 +528,20 @@ possono avere proviamo allora con un servizio leggermente pi
   \label{fig:UDP_echo_client}
 \end{figure}
 
-In fig.~\ref{fig:UDP_echo_client} è riportato un estratto del corpo principale
+In fig.~\ref{fig:UDP_echo_client} è riportato un estratto del corpo principale
 del nostro client elementare per il servizio \textit{echo} (al solito il
-codice completo è con i sorgenti allegati). Le uniche differenze con l'analogo
+codice completo è con i sorgenti allegati). Le uniche differenze con l'analogo
 client visto in fig.~\ref{fig:TCP_echo_client_1} sono che al solito si crea
-(\texttt{\small 14}) un socket di tipo \const{SOCK\_DGRAM}, e che non è
+(\texttt{\small 14}) un socket di tipo \const{SOCK\_DGRAM}, e che non è
 presente nessuna chiamata a \func{connect}. Per il resto il funzionamento del
-programma è identico, e tutto il lavoro viene effettuato attraverso la
+programma è identico, e tutto il lavoro viene effettuato attraverso la
 chiamata (\texttt{\small 28}) alla funzione \func{ClientEcho} che stavolta
-però prende un argomento in più, che è l'indirizzo del socket.
+però prende un argomento in più, che è l'indirizzo del socket.
 
-\begin{figure}[!htb] 
+\begin{figure}[!htbp
   \footnotesize \centering
-  \begin{minipage}[c]{15.6cm}
-    \includecodesample{listati/UDP_ClientEcho.c}
+  \begin{minipage}[c]{\codesamplewidth}
+    \includecodesample{listati/UDP_ClientEcho_first.c}
   \end{minipage}
   \normalsize
   \caption{Codice della funzione \func{ClientEcho} usata dal client per il
@@ -527,27 +549,27 @@ per
   \label{fig:UDP_echo_client_echo}
 \end{figure}
 
-Ovviamente in questo caso il funzionamento della funzione, il cui codice è
-riportato in fig.~\ref{fig:UDP_echo_client_echo}, è completamente diverso
+Ovviamente in questo caso il funzionamento della funzione, il cui codice è
+riportato in fig.~\ref{fig:UDP_echo_client_echo}, è completamente diverso
 rispetto alla analoga del server TCP, e dato che non esiste una connessione
-questa necessita anche di un terzo argomento, che è l'indirizzo del server cui
+questa necessita anche di un terzo argomento, che è l'indirizzo del server cui
 inviare i pacchetti.
 
-Data l'assenza di una connessione come nel caso di TCP il meccanismo è molto
-più semplice da gestire. Al solito si esegue un ciclo infinito (\texttt{\small
+Data l'assenza di una connessione come nel caso di TCP il meccanismo è molto
+più semplice da gestire. Al solito si esegue un ciclo infinito (\texttt{\small
   6--30}) che parte dalla lettura (\texttt{\small 7}) sul buffer di invio
-\var{sendbuff} di una stringa dallo standard input, se la stringa è vuota
-(\texttt{\small 7--9}), indicando che l'input è terminato, si ritorna
+\var{sendbuff} di una stringa dallo standard input, se la stringa è vuota
+(\texttt{\small 7--9}), indicando che l'input è terminato, si ritorna
 immediatamente causando anche la susseguente terminazione del programma.
 
 Altrimenti si procede (\texttt{\small 10--11}) all'invio della stringa al
 destinatario invocando \func{sendto}, utilizzando, oltre alla stringa appena
 letta, gli argomenti passati nella chiamata a \func{ClientEcho}, ed in
-particolare l'indirizzo del server che si è posto in \var{serv\_addr}; qualora
-(\texttt{\small 12}) si riscontrasse un errore si provvederà al solito
+particolare l'indirizzo del server che si è posto in \var{serv\_addr}; qualora
+(\texttt{\small 12}) si riscontrasse un errore si provvederà al solito
 (\texttt{\small 13--14}) ad uscire con un messaggio di errore.
 
-Il passo immediatamente seguente (\texttt{\small 17}) l'invio è quello di
+Il passo immediatamente seguente (\texttt{\small 17}) l'invio è quello di
 leggere l'eventuale risposta del server con \func{recvfrom}; si noti come in
 questo caso si sia scelto di ignorare l'indirizzo dell'eventuale pacchetto di
 risposta, controllando (\texttt{\small 18--21}) soltanto la presenza di un
@@ -558,15 +580,15 @@ sez.~\ref{sec:TCP_echo_client} non si sia controllato il caso di un messaggio
 nullo, dato che, nel caso di socket UDP, questo non significa la terminazione
 della comunicazione.
 
-L'ultimo passo (\texttt{\small 17}) è quello di terminare opportunamente la
+L'ultimo passo (\texttt{\small 17}) è quello di terminare opportunamente la
 stringa di risposta nel relativo buffer per poi provvedere alla sua stampa
 sullo standard output, eseguendo il solito controllo (ed eventuale uscita con
 adeguato messaggio informativo) in caso di errore.
 
-In genere fintanto che si esegue il nostro client in locale non sorgerà nessun
-problema, se però si proverà ad eseguirlo attraverso un collegamento remoto
+In genere fintanto che si esegue il nostro client in locale non sorgerà nessun
+problema, se però si proverà ad eseguirlo attraverso un collegamento remoto
 (nel caso dell'esempio seguente su una VPN, attraverso una ADSL abbastanza
-congestionata) e in modalità non interattiva, la probabilità di perdere
+congestionata) e in modalità non interattiva, la probabilità di perdere
 qualche pacchetto aumenta, ed infatti, eseguendo il comando come:
 \begin{verbatim}
 [piccardi@gont sources]$ cat UDP_echo.c | ./echo 192.168.1.120
@@ -579,8 +601,8 @@ qualche pacchetto aumenta, ed infatti, eseguendo il comando come:
  * Include needed headers
 
 \end{verbatim}%$
-si otterrà che, dopo aver correttamente stampato alcune righe, il programma si
-blocca completamente senza stampare più niente. Se al contempo si fosse tenuto
+si otterrà che, dopo aver correttamente stampato alcune righe, il programma si
+blocca completamente senza stampare più niente. Se al contempo si fosse tenuto
 sotto controllo il traffico UDP diretto o proveniente dal servizio
 \textit{echo} con \cmd{tcpdump} si sarebbe ottenuto:
 \begin{verbatim}
@@ -594,15 +616,15 @@ sotto controllo il traffico UDP diretto o proveniente dal servizio
 18:48:17.965408 gont.earthsea.ea.32788 > 192.168.1.120.echo: udp 4 (DF)
 \end{verbatim}
 che come si vede il traffico fra client e server si interrompe dopo l'invio di
-un pacchetto UDP per il quale non si è ricevuto risposta.
-
-Il problema è che in tutti i casi in cui un pacchetto di risposta si perde, o
-una richiesta non arriva a destinazione, il nostro programma si bloccherà
-nell'esecuzione di \func{recvfrom}. Lo stesso avviene anche se il server non è
-in ascolto, in questo caso però, almeno dal punto di vista dello scambio di
-pacchetti, il risultato è diverso, se si lancia al solito il programma e si
-prova a scrivere qualcosa si avrà ugualmente un blocco su \func{recvfrom} ma
-se si osserva il traffico con \cmd{tcpdump} si vedrà qualcosa del tipo:
+un pacchetto UDP per il quale non si è ricevuto risposta.
+
+Il problema è che in tutti i casi in cui un pacchetto di risposta si perde, o
+una richiesta non arriva a destinazione, il nostro programma si bloccherà
+nell'esecuzione di \func{recvfrom}. Lo stesso avviene anche se il server non è
+in ascolto, in questo caso però, almeno dal punto di vista dello scambio di
+pacchetti, il risultato è diverso, se si lancia al solito il programma e si
+prova a scrivere qualcosa si avrà ugualmente un blocco su \func{recvfrom} ma
+se si osserva il traffico con \cmd{tcpdump} si vedrà qualcosa del tipo:
 \begin{verbatim}
 [root@gont gapil]# tcpdump  \( dst 192.168.0.2 and src 192.168.1.120 \) \
    or \( src 192.168.0.2 and dst 192.168.1.120 \)
@@ -611,35 +633,35 @@ tcpdump: listening on eth0
 00:43:27.990560 192.168.1.120 > gont.earthsea.ea: icmp: 192.168.1.120 udp port 
 echo unreachable [tos 0xc0]
 \end{verbatim}
-cioè in questo caso si avrà in risposta un pacchetto ICMP di destinazione
+cioè in questo caso si avrà in risposta un pacchetto ICMP di destinazione
 irraggiungibile che ci segnala che la porta in questione non risponde. 
 
-Ci si può chiedere allora perché, benché la situazione di errore sia
-rilevabile, questa non venga segnalata. Il luogo più naturale in cui
-riportarla sarebbe la chiamata di \func{sendto}, in quanto è a causa dell'uso
-di un indirizzo sbagliato che il pacchetto non può essere inviato; farlo in
-questo punto però è impossibile, dato che l'interfaccia di programmazione
+Ci si può chiedere allora perché, benché la situazione di errore sia
+rilevabile, questa non venga segnalata. Il luogo più naturale in cui
+riportarla sarebbe la chiamata di \func{sendto}, in quanto è a causa dell'uso
+di un indirizzo sbagliato che il pacchetto non può essere inviato; farlo in
+questo punto però è impossibile, dato che l'interfaccia di programmazione
 richiede che la funzione ritorni non appena il kernel invia il
-pacchetto,\footnote{questo è il classico caso di \textsl{errore asincrono},
-  una situazione cioè in cui la condizione di errore viene rilevata in maniera
-  asincrona rispetto all'operazione che l'ha causata, una eventualità
+pacchetto,\footnote{questo è il classico caso di \textsl{errore asincrono},
+  una situazione cioè in cui la condizione di errore viene rilevata in maniera
+  asincrona rispetto all'operazione che l'ha causata, una eventualità
   piuttosto comune quando si ha a che fare con la rete, tutti i pacchetti ICMP
-  che segnalano errori rientrano in questa tipologia.} e non può bloccarsi in
+  che segnalano errori rientrano in questa tipologia.} e non può bloccarsi in
 una attesa di una risposta che potrebbe essere molto lunga (si noti infatti
-che il pacchetto ICMP arriva qualche decimo di secondo più tardi) o non
+che il pacchetto ICMP arriva qualche decimo di secondo più tardi) o non
 esserci affatto.
 
-Si potrebbe allora pensare di riportare l'errore nella \func{recvfrom} che è
-comunque bloccata in attesa di una risposta che nel caso non arriverà mai.  La
-ragione per cui non viene fatto è piuttosto sottile e viene spiegata da
+Si potrebbe allora pensare di riportare l'errore nella \func{recvfrom} che è
+comunque bloccata in attesa di una risposta che nel caso non arriverà mai.  La
+ragione per cui non viene fatto è piuttosto sottile e viene spiegata da
 Stevens in \cite{UNP2} con il seguente esempio: si consideri un client che
 invia tre pacchetti a tre diverse macchine, due dei quali vengono regolarmente
 ricevuti, mentre al terzo, non essendo presente un server sulla relativa
 macchina, viene risposto con un messaggio ICMP come il precedente. Detto
-messaggio conterrà anche le informazioni relative ad indirizzo e porta del
-pacchetto che ha fallito, però tutto quello che il kernel può restituire al
-programma è un codice di errore in \var{errno}, con il quale è impossibile di
-distinguere per quale dei pacchetti inviati si è avuto l'errore; per questo è
+messaggio conterrà anche le informazioni relative ad indirizzo e porta del
+pacchetto che ha fallito, però tutto quello che il kernel può restituire al
+programma è un codice di errore in \var{errno}, con il quale è impossibile di
+distinguere per quale dei pacchetti inviati si è avuto l'errore; per questo è
 stata fatta la scelta di non riportare un errore su un socket UDP, a meno che,
 come vedremo in sez.~\ref{sec:UDP_connect}, questo non sia connesso.
 
@@ -649,68 +671,159 @@ come vedremo in sez.~\ref{sec:UDP_connect}, questo non sia connesso.
 \label{sec:UDP_connect}
 
 Come illustrato in sez.~\ref{sec:UDP_characteristics} essendo i socket UDP
-privi di connessione non è necessario per i client usare \func{connect} prima
-di iniziare una comunicazione con un server. Ciò non di meno abbiamo accennato
+privi di connessione non è necessario per i client usare \func{connect} prima
+di iniziare una comunicazione con un server. Ciò non di meno abbiamo accennato
 come questa possa essere utilizzata per gestire la presenza di errori
 asincroni.
 
-Quando si chiama \func{connect} su di un socket UDP tutto quello che succede è
+Quando si chiama \func{connect} su di un socket UDP tutto quello che succede è
 che l'indirizzo passato alla funzione viene registrato come indirizzo di
-destinazione del socket, a differenza di quanto avviene con TCP non viene
-scambiato nessun pacchetto; tutto quello che succede è che da quel momento in
-qualunque cosa si scriva sul socket sarà inviata a quell'indirizzo; non sarà
-più necessario usare l'argomento \param{to} di \func{sendto} per specificare
+destinazione del socket. A differenza di quanto avviene con TCP non viene
+scambiato nessun pacchetto, tutto quello che succede è che da quel momento in
+qualunque cosa si scriva sul socket sarà inviata a quell'indirizzo; non sarà
+più necessario usare l'argomento \param{to} di \func{sendto} per specificare
 la destinazione dei pacchetti, che potranno essere inviati e ricevuti usando
-le normali funzioni \func{read} e \func{write}.\footnote{in realtà si può
-  anche continuare ad usare la funzione \func{sendto}, ma in tal caso
-  l'argomento \param{to} deve essere inizializzato a \const{NULL}, e
-  \param{tolen} deve essere inizializzato a zero, pena un errore.}
-
-Una volta che il socket è connesso però cambia anche il comportamento in
+le normali funzioni \func{read} e \func{write} che a questo punto non
+falliranno più con l'errore di \errval{EDESTADDRREQ}.\footnote{in realtà si
+  può anche continuare ad usare la funzione \func{sendto}, ma in tal caso
+  l'argomento \param{to} deve essere inizializzato a \val{NULL}, e
+  \param{tolen} deve essere inizializzato a zero, pena un errore di
+  \errval{EISCONN}.}
+
+Una volta che il socket è connesso cambia però anche il comportamento in
 ricezione; prima infatti il kernel avrebbe restituito al socket qualunque
 pacchetto ricevuto con un indirizzo di destinazione corrispondente a quello
 del socket, senza nessun controllo sulla sorgente; una volta che il socket
 viene connesso saranno riportati su di esso solo i pacchetti con un indirizzo
-sorgente corrispondente a quello a cui ci si è connessi. 
+sorgente corrispondente a quello a cui ci si è connessi.
 
-Infine quando si è connesso un socket, venendo meno l'ambiguità segnalata alla
-fine di sez.~\ref{sec:UDP_problems}, tutti gli eventuali errori asincroni
-vengono riportati alle funzioni che operano su di esse, pertanto con le
-modifiche illustrate in fig.~\ref{fig:UDP_echo_conn_cli}.
+Infine quando si usa un socket connesso, venendo meno l'ambiguità segnalata
+alla fine di sez.~\ref{sec:UDP_problems}, tutti gli eventuali errori asincroni
+vengono riportati alle funzioni che operano su di esso; pertanto potremo
+riscrivere il nostro client per il servizio \textit{echo} con le modifiche
+illustrate in fig.~\ref{fig:UDP_echo_conn_cli}.
 
-\begin{figure}[!htb] 
+\begin{figure}[!htbp
   \footnotesize \centering
-  \begin{minipage}[c]{15.6cm}
+  \begin{minipage}[c]{\codesamplewidth}
     \includecodesample{listati/UDP_echo.c}
   \end{minipage}
   \normalsize
-  \caption{Nuova sezione della seconda versione del client del servizio
-    \textit{echo} che utilizza socket UDP connessi.}
+  \caption{Seconda versione del client del servizio \textit{echo} che utilizza
+    socket UDP connessi.}
   \label{fig:UDP_echo_conn_cli}
 \end{figure}
 
+Ed in questo caso rispetto alla precedente versione, il solo cambiamento è
+l'utilizzo (\texttt{\small 17}) della funzione \func{connect} prima della
+chiamata alla funzione di gestione del protocollo, che a sua volta è stata
+modificata eliminando l'indirizzo passato come argomento e sostituendo le
+chiamata a \func{sendto} e \func{recvfrom} con chiamate a \func{read} e
+\func{write} come illustrato dal nuovo codice riportato in
+fig.~\ref{fig:UDP_echo_conn_echo_client}.
+
+\begin{figure}[!htbp] 
+  \footnotesize \centering
+  \begin{minipage}[c]{\codesamplewidth}
+    \includecodesample{listati/UDP_ClientEcho.c}
+  \end{minipage}
+  \normalsize
+  \caption{Seconda versione della funzione \func{ClientEcho}.}
+  \label{fig:UDP_echo_conn_echo_client}
+\end{figure}
+
+Utilizzando questa nuova versione del client si può verificare che quando ci
+si rivolge verso un indirizzo inesistente o su cui non è in ascolto un server
+si è in grado rilevare l'errore, se infatti eseguiamo il nuovo programma
+otterremo un qualcosa del tipo:
+\begin{verbatim}
+[piccardi@gont sources]$ ./echo 192.168.1.1
+prova
+Errore in lettura: Connection refused
+\end{verbatim}%$
+
+Ma si noti che a differenza di quanto avveniva con il client TCP qui l'errore
+viene rilevato soltanto dopo che si è tentato di inviare qualcosa, ed in
+corrispondenza al tentativo di lettura della risposta. Questo avviene perché
+con UDP non esiste una connessione, e fintanto che non si invia un pacchetto
+non c'è traffico sulla rete. In questo caso l'errore sarà rilevato alla
+ricezione del pacchetto ICMP \textit{destination unreachable} emesso dalla
+macchina cui ci si è rivolti, e questa volta, essendo il socket UDP connesso,
+il kernel potrà riportare detto errore in \textit{user space} in maniera non
+ambigua, ed esso apparirà alla successiva lettura sul socket.
+
+Si tenga presente infine che l'uso dei socket connessi non risolve l'altro
+problema del client, e cioè il fatto che in caso di perdita di un pacchetto
+questo resterà bloccato permanentemente in attesa di una risposta. Per
+risolvere questo problema l'unico modo sarebbe quello di impostare un
+\textit{timeout} o riscrivere il client in modo da usare l'I/O non bloccante.
+
+
 
+\index{socket!locali|(}
 
 
 \section{I socket \textit{Unix domain}}
 \label{sec:unix_socket}
 
-Benché i socket Unix domain non siano strettamente attinenti alla rete, in
-quanto definiscono una interfaccia di comunicazione locale alla singola
-macchina, li tratteremo comunque in questa sezione in quanto la loro
-interfaccia è comunque basata sulla più generale interfaccia dei socket.
+Benché i socket Unix domain, come meccanismo di comunicazione fra processi che
+girano sulla stessa macchina, non siano strettamente attinenti alla rete, li
+tratteremo comunque in questa sezione. Nonostante le loro peculiarità infatti,
+l'interfaccia di programmazione che serve ad utilizzarli resta sempre quella
+dei socket.
+
+
+
+\subsection{Il passaggio di file descriptor}
+\label{sec:sock_fd_passing}
+
+
+
+\index{socket!locali|)}
 
 
 \section{Altri socket}
 \label{sec:socket_other}
 
-
 Tratteremo in questa sezione gli altri tipi particolari di socket supportati
-da Linux, come i \textit{raw socket}, con i quali si possono \textsl{forgiare}
-direttamente i pacchetti a tutti i livelli dello stack dei protocolli, o i
+da Linux, come quelli relativi a particolare protocolli di trasmissione, i
 socket \textit{netlink} che definiscono una interfaccia di comunicazione con
-il kernel.
+il kernel, ed i \textit{packet socket} che consentono di inviare pacchetti
+direttamente a livello delle interfacce di rete. 
+
+\subsection{I socket \textit{raw}}
+\label{sec:socket_raw}
+
+Tratteremo in questa sezione i cosiddetti \textit{raw socket}, con i quali si
+possono \textsl{forgiare} direttamente i pacchetti a tutti i livelli dello
+stack dei protocolli. 
+
+\subsection{I socket \textit{netlink}}
+\label{sec:socket_netlink}
+
+
+\subsection{I \textit{packet socket}}
+\label{sec:packet_socket}
+
+
+% articoli interessanti:
+% http://www.linuxjournal.com/article/5617
+% http://www.linuxjournal.com/article/4659
+% 
+
 
+% LocalWords:  socket cap TCP UDP domain sez NFS DNS stream datagram PF INET to
+% LocalWords:  IPv tab SOCK DGRAM three way handshake client fig bind listen AF
+% LocalWords:  accept recvfrom sendto connect netstat named DHCP kernel ICMP CR
+% LocalWords:  port unreachable read write glibc Specification flags int BSD LF
+% LocalWords:  libc unsigned len size tolen sys ssize sockfd const void buf MSG
+% LocalWords:  struct sockaddr socklen errno EAGAIN ECONNRESET EDESTADDRREQ RFC
+% LocalWords:  EISCONN EMSGSIZE ENOBUFS ENOTCONN EOPNOTSUPP EPIPE SIGPIPE EBADF
+% LocalWords:  NOSIGNAL EFAULT EINVAL EINTR ENOMEM ENOTSOCK NULL fromlen from
+% LocalWords:  ECONNREFUSED value result argument close shutdown daytime nell'
+% LocalWords:  memset inet pton nread NUL superdemone inetd sniffer daytimed
+% LocalWords:  INADDR ANY addr echo ClientEcho sendbuff serv VPN tcpdump l'I
+% LocalWords:  Stevens destination descriptor raw stack netlink packet