Messo esempio di server elementare.
[gapil.git] / othersock.tex
index d7bc4c0e520f533aa96d408f139a64e35651097f..00ee9c6619378a94f1b9a11561e9983840efcc51 100644 (file)
@@ -8,19 +8,20 @@
 %% license is included in the section entitled "GNU Free Documentation
 %% License".
 %%
-\chapter{Gli altri socket più comuni}
+\chapter{Gli altri tipi di socket}
 \label{cha:other_socket}
 
 Dopo aver trattato in \capref{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, 
+capitolo gli altri tipi di socket, a partire dai socket UDP, e i socket deiit
+\textit{Unix domain} già incontrati in \secref{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
-socket UDP; protocolli diffusi come NFS o il DNS usano principalmente questo
+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.
 
@@ -29,30 +30,34 @@ principali e le modalit
 \label{sec:UDP_characteristics}
 
 Come illustrato in \secref{sec:net_udp} UDP è un protocollo molto semplice che
-non supporta le connessioni e non è affidabile: i dati vengono inviati in
-forma di pacchetti, e non ne è assicurata né la effettiva ricezione né
-l'odinamento.
+non supporta le connessioni e non è affidabile: esso si appoggia direttamente
+sopra IP (per i dettagli sul protocollo si veda \secref{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ù
+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 di tipo
-\textit{datagram}, in cui i dati arrivano in singoli blocchi che devono essere
-letti integralmente.
-
-Questo diverso comportamento significa anche che i socket UDP, pur restando
-nella famiglia \const{PF\_INET}\footnote{o \const{PF\_INET6} qualora si usasse
-  invece il protocollo IPv6.} devono essere aperti quando si usa la funzione
-\func{socket} (si riveda quanto illustrato a suo tempo in
-\tabref{tab:sock_sock_valid_combinations}) utilizzando come valore per il tipo
-di socket \const{SOCK\_DGRAM}.
-
-Questa differenza comporta ovviamente il fatto che anche le modalità con cui
-si usano i socket UDP sono completamente diverse rispetto ai socket TCP, ed in
+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.
+
+Questo diverso comportamento significa anche che i socket UDP, pur
+appartenendo alla famiglia \const{PF\_INET}\footnote{o \const{PF\_INET6}
+  qualora si usasse invece il protocollo IPv6, che pure supporta UDP.} devono
+essere aperti quando si usa la funzione \func{socket} (si riveda quanto
+illustrato a suo tempo in \tabref{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
+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 di 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 \figref{fig:UDP_packet-exchange}.
+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 \figref{fig:UDP_packet-exchange}.
 
 \begin{figure}[htb]
   \centering
@@ -62,20 +67,395 @@ schema illustrato in \figref{fig:UDP_packet-exchange}.
   \label{fig:UDP_packet-exchange}
 \end{figure}
 
-Anche se UDP è completamente diverso rispetto a TCP resta identica 
+Come illustrato in \figref{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
+\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}. 
+
+Da parte del client invece, una volta creato il socket non sarà necessario
+connettersi con \func{connect} (anche se, come vedremo in
+\secref{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
+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
+verificare quali socket sono in ascolto:
+\begin{verbatim}
+[piccardi@gont gapil]# netstat -anu
+Active Internet connections (servers and established)
+Proto Recv-Q Send-Q Local Address           Foreign Address         State
+udp        0      0 0.0.0.0:32768           0.0.0.0:*
+udp        0      0 192.168.1.2:53          0.0.0.0:*
+udp        0      0 127.0.0.1:53            0.0.0.0:*
+udp        0      0 0.0.0.0:67              0.0.0.0:*
+\end{verbatim}
+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
+socket UDP infatti non hanno uno stato. Inoltre anche in presenza di traffico
+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
+  unreachable} qualora non vi sia nessun processo in ascolto.
 
 
 \subsection{Le funzioni \func{sendto} e \func{recvfrom}}
 \label{sec:UDP_sendto_recvfrom}
 
-Come accennato le due funzioni principali usate per la trasmissione di dati
-attraverso i socket UDP, ma in generale attraverso qualunque socket che
-preveda una comunicazione a pacchetti, sono \func{sendto} e \func{recvfrom}.
+Come accennato in \secref{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.
+
+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 attraveso 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
+  \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}.} è:
+\begin{functions}
+  \headdecl{sys/types.h}
+  \headdecl{sys/socket.h}
+  
+  \funcdecl{ssize\_t sendto(int sockfd, const void *buf, size\_t len, int
+    flags, const struct sockaddr *to, socklen\_t tolen)}
+  
+  Trasmette un messaggio ad un altro socket.
+  
+  \bodydesc{La funzione restituisce il numero di caratteri inviati in caso di
+    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
+    l'operazione richede che la funzione si blocchi.
+  \item[\errcode{ECONNRESET}] l'altro capo della comunicazione ha resettato la
+    conessione.
+  \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
+    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
+    norma Linux non usa questo messaggio ma scarta silenziosamente i
+    pacchetti).
+  \item[\errcode{ENOTCONN}] il socket non è connesso e non si è specificata
+    una destinazione.
+  \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
+    \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
+  ai protocolli utilizzati.}
+\end{functions}
+
+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
+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é
+eccede le dimensioni massime del protocollo sottostante utilizzato) essa
+fallisce con l'errore di \errcode{EMSGSIZE}. 
+
+I due argomenti \param{to} e \param{tolen} servono a specificare la
+destinazione del messaggio da inviare, e indicano rispettivamente la struttura
+contentente 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} devrà 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
+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
+specifico caso in cui gli argomenti \param{to} e \param{tolen} non servono
+essi devranno essere inizializzati rispettivamente a \const{NULL} e 0;
+normalmente quando si opera su un socket conesso essi vengono ignorati, ma
+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
+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 \secref{sec:xxx_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 è
+\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
+  \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}.} è:
+\begin{functions}
+  \headdecl{sys/types.h}
+  \headdecl{sys/socket.h}
+  
+  \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.
+  
+  \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
+    valore:
+  \begin{errlist}
+  \item[\errcode{EAGAIN}] il socket è in modalità non bloccante, ma
+    l'operazione richede 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.
+  \end{errlist}
+  ed anche \errval{EFAULT}, \errval{EBADF}, \errval{EINVAL}, \errval{EINTR},
+  \errval{ENOMEM}, \errval{ENOTSOCK} più gli eventuali altri errori relativi
+  ai protocolli utilizzati.}
+\end{functions}
+
+Come per \func{sendto} i primi tre argomenti sono identici agli analoghi di
+\func{read}: dal socket vengono letti \param{len} byte che vengono salvati nel
+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
+\errcode{EAGAIN}.  Qualora \param{len} ecceda la dimensione del pacchetto la
+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
+  argoment}).  Se non si è interessati a questa informazione, entrambi gli
+argomenti devono essere inizializzati al valore \const{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
+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
+  \func{close} o \func{shutdown} per terminare la cominicazione.} o come una
+cessazione delle comunicazioni.
+
+
+
+\subsection{Un client UDP elementare}
+\label{sec:UDP_daytime_client}
+
+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},
+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
+sua volta un pacchetto UDP contenente la data.
+
+\begin{figure}[!htb] 
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/UDP_daytime.c}
+  \end{minipage} 
+  \normalsize
+  \caption{Sezione principale del client per il servizio \textit{daytime} su
+    UDP.}
+  \label{fig:UDP_daytime_client}
+\end{figure}
+
+In \figref{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
+gestione delle opzioni a riga di comando (nel caso praticamente assenti).
+
+Il programma inizia (\texttt{\small 9--12}) con la creazione del socket, al
+solito uscendo dopo aver stampato un messaggio in caso errore. Si noti come in
+questo caso, rispetto all'analogo client basato su socket TCP di
+\figref{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
+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
+\figref{fig:TCP_daytime_client_code}, in quanto la determinazione dell'uso 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
+pacchetto al server. Questo lo si fa (\texttt{\small 16}) inviando un
+pacchetto vuoto (si ricordi quanto detto in \secref{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.
+
+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
+lettura\footnote{si ricordi che, come illustrato in
+  \secref{sec:TCP_daytime_client}, il server invia in risposta una stringa
+  contenente la data, terminata dai due carratteri CR e LF, che pertanto prima
+  di essere stampata deve essere opportunamente terminata con un NUL.} e a
+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
+  \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
+quest'ultimo con:
+\begin{verbatim}
+[piccardi@gont sources]$ ./daytime 127.0.0.1
+Sat Mar 20 23:17:13 2004
+\end{verbatim}%$
+ed osservando il traffico con uno sniffer potremo effettivamente vedere lo
+scambio dei due pacchetti, quello vuoto di richiesta, e la risposta del
+server:
+\begin{verbatim}
+[root@gont gapil]# tcpdump -i lo
+tcpdump: listening on lo
+23:41:21.645579 localhost.32780 > localhost.daytime: udp 0 (DF)
+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
+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
+ascolto sull'indirizzo di destinazione. Questo comporta ad esempio che se si
+usa il nostro programma interrogando un server inesistente questo resterà
+perennemente bloccato nella chiamata a \func{recvfrom}, fin quando non lo
+interromperemo. Vedremo in \secref{sec:UDP_connect} come si può porre rimedio
+a questa problematica.
+
+
+
+\subsection{Un server UDP elementare}
+\label{sec:UDP_daytime_server}
+
+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
+pacchetto di richiesta ed inviare in risposta un pacchetto contenente una
+stringa con la data corrente. 
+
+\begin{figure}[!htb] 
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/UDP_daytimed.c}
+  \end{minipage} 
+  \normalsize
+  \caption{Sezione principale del server per il servizio \textit{daytime} su
+    UDP.}
+  \label{fig:UDP_daytime_server}
+\end{figure}
+
+In \figref{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
+video l'indirizzo associato ad ogni richiesta).
+
+Anche in questo caso la prima parte del server (\texttt{\small 9--23}) è
+sostanzialmente identica a quella dell'analogo server per TCP illustrato in
+\figref{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à
+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 \secref{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
+(\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
+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
+macchina che ha inviato il pacchetto con un messaggio ICMP di tipo
+\textit{port unreachable}.
+
+
+
+
+\subsection{L'uso della funzione \func{connect} con i socket UDP}
+\label{sec:UDP_connect}
+
+Come illustrato in \secref{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.
+
 
 
 \section{I socket \textit{Unix domain}}
-\label{sec:UDP_socket}
+\label{sec:unix_socket}
 
 Benché i socket Unix domain non siano strattamente attinenti alla rete, in
 quanto definiscono una interfaccia di comunicazione locale alla singola
@@ -85,6 +465,7 @@ interfaccia 
 
 
 
+
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"