+\begin{prototype}{sys/socket.h}
+ {char *inet\_ntop(int af, const void *addr\_ptr, char *dest, size\_t len)}
+ Converte l'indirizzo dalla relativa struttura in una stringa simbolica.
+
+ \bodydesc{La funzione restituisce un puntatore non nullo alla stringa
+ convertita in caso di successo e \val{NULL} in caso di fallimento, nel
+ qual caso \var{errno} assume i valor:
+ \begin{errlist}
+ \item[\errcode{ENOSPC}] le dimensioni della stringa con la conversione
+ dell'indirizzo eccedono la lunghezza specificata da \var{len}.
+ \item[\errcode{ENOAFSUPPORT}] la famiglia di indirizzi \var{af} non è una
+ valida.
+ \end{errlist}}
+\end{prototype}
+
+La funzione converte la struttura dell'indirizzo puntata da \var{addr\_ptr} in
+una stringa che viene copiata nel buffer puntato dall'indirizzo \var{dest};
+questo deve essere preallocato dall'utente e la lunghezza deve essere almeno
+\const{INET\_ADDRSTRLEN} in caso di indirizzi IPv4 e \const{INET6\_ADDRSTRLEN}
+per indirizzi IPv6; la lunghezza del buffer deve comunque venire specificata
+attraverso il parametro \var{len}.
+
+Gli indirizzi vengono convertiti da/alle rispettive strutture di indirizzo
+(\var{struct in\_addr} per IPv4, e \var{struct in6\_addr} per IPv6), che
+devono essere precedentemente allocate e passate attraverso il puntatore
+\var{addr\_ptr}; il parametro \var{dest} di \func{inet\_ntop} non può essere
+nullo e deve essere allocato precedentemente.
+
+Il formato usato per gli indirizzi in formato di presentazione è la notazione
+\textit{dotted decimal} per IPv4 e quello descritto in
+\secref{sec:IP_ipv6_notation} per IPv6.
+
+\index{socket|)}
+
+
+\section{Un esempio di applicazione}
+\label{sec:sock_appplication}
+
+Per evitare di rendere questa introduzione ai socket puramente teorica
+iniziamo con il mostrare un esempio di un client TCP elementare. Prima di
+passare agli esempi del client e del server, ritorniamo con maggiori dettagli
+su una caratteristica delle funzioni di I/O che nel caso dei socket è
+particolarmente rilevante, e che ci tornerà utile anche in seguito.
+
+
+\subsection{Il comportamento delle funzioni di I/O}
+\label{sec:sock_io_behav}
+
+Una cosa di cui non sempre si è consapevoli quando si ha a che fare con i
+socket è che le funzioni di input/output non sempre hanno lo stesso
+comportamento che avrebbero con i normali files (in particolare questo accade
+per i socket di tipo stream).
+
+Infatti con i socket è comune che funzioni come \func{read} o \func{write}
+possano restituire in input o scrivere in output un numero di byte minore di
+quello richiesto. Come già accennato in \secref{sec:file_read} questo è un
+comportamento normale per l'I/O su file; con i normali file di dati il
+problema si avverte solo quando si incontra la fine del file, ma in generale
+non è così.
+
+In questo caso tutto quello che il programma chiamante deve fare è di ripetere
+la lettura (o scrittura) per la quantità di byte rimanenti (e le funzioni si
+possono bloccare se i dati non sono disponibili): è lo stesso comportamento
+che si può avere scrivendo più di \const{PIPE\_BUF} byte in una pipe (si
+riveda quanto detto in \secref{sec:ipc_pipes}).
+
+\begin{figure}[htb]
+ \centering
+ \footnotesize
+ \begin{lstlisting}{}
+#include <unistd.h>
+
+ssize_t SockRead(int fd, void *buf, size_t count)
+{
+ size_t nleft;
+ ssize_t nread;
+
+ nleft = count;
+ while (nleft > 0) { /* repeat until no left */
+ if ( (nread = read(fd, buf, nleft)) < 0) {
+ if (errno == EINTR) { /* if interrupted by system call */
+ continue; /* repeat the loop */
+ } else {
+ return(nread); /* otherwise exit */
+ }
+ } else if (nread == 0) { /* EOF */
+ break; /* break loop here */
+ }
+ nleft -= nread; /* set left to read */
+ buf +=nread; /* set pointer */
+ }
+ return (count - nleft);
+}
+ \end{lstlisting}
+ \caption{Funzione \func{SockRead}, legge \var{count} byte da un socket }
+ \label{fig:sock_SockRead_code}
+\end{figure}
+
+Per questo motivo, seguendo l'esempio di W. R. Stevens in \cite{UNP1}, si sono
+definite due funzioni \func{SockRead} e \func{SockWrite} che eseguono la
+lettura da un socket tenendo conto di questa caratteristica, ed in grado di
+ritornare dopo avere letto o scritto esattamente il numero di byte
+specificato; il sorgente è riportato in \figref{fig:sock_SockRead_code} e
+\figref{fig:sock_SockWrite_code} ed è disponibile fra i sorgenti allegati alla
+guida nei files \file{SockRead.c} e \file{SockWrite.c}.
+
+\begin{figure}[htb]
+ \centering
+ \footnotesize
+ \begin{lstlisting}{}
+#include <unistd.h>
+
+ssize_t SockWrite(int fd, const void *buf, size_t count)
+{
+ size_t nleft;
+ ssize_t nwritten;
+
+ nleft = count;
+ while (nleft > 0) { /* repeat until no left */
+ if ( (nwritten = write(fd, buf, nleft)) < 0) {
+ if (errno == EINTR) { /* if interrupted by system call */
+ continue; /* repeat the loop */
+ } else {
+ return(nwritten); /* otherwise exit with error */
+ }
+ }
+ nleft -= nwritten; /* set left to write */
+ buf +=nwritten; /* set pointer */
+ }
+ return (count);
+}
+ \end{lstlisting}
+ \caption{Funzione \func{SockWrite}, scrive \var{count} byte su un socket }
+ \label{fig:sock_SockWrite_code}
+\end{figure}
+
+Come si può notare le funzioni ripetono la lettura/scrittura in un ciclo fino
+all'esaurimento del numero di byte richiesti, in caso di errore viene
+controllato se questo è \errcode{EINTR} (cioè un'interruzione della system call
+dovuta ad un segnale), nel qual caso l'accesso viene ripetuto, altrimenti
+l'errore viene ritornato interrompendo il ciclo.
+
+Nel caso della lettura, se il numero di byte letti è zero, significa che si è
+arrivati alla fine del file (per i socket questo significa in genere che
+l'altro capo è stato chiuso, e non è quindi più possibile leggere niente) e
+pertanto si ritorna senza aver concluso la lettura di tutti i byte richiesti.
+
+
+
+\subsection{Un primo esempio di client}
+\label{sec:net_cli_sample}
+
+Lo scopo di questo esempio è fornire un primo approccio alla programmazione di
+rete e vedere come si usano le funzioni descritte in precedenza, alcune delle
+funzioni usate nell'esempio saranno trattate in dettaglio nel capitolo
+successivo; qui ci limiteremo a introdurre la nomenclatura senza fornire
+definizioni precise e dettagli di funzionamento che saranno trattati
+estensivamente più avanti.
+
+In \figref{fig:net_cli_code} è riportata la sezione principale del codice del
+nostro client elementare per il servizio \textit{daytime}, un servizio
+standard che restituisce l'ora locale della macchina a cui si effettua la
+richiesta.
+
+\begin{figure}[!htb]
+ \footnotesize
+ \begin{lstlisting}{}
+#include <sys/types.h> /* predefined types */
+#include <unistd.h> /* include unix standard library */
+#include <arpa/inet.h> /* IP addresses conversion utilities */
+#include <sys/socket.h> /* socket library */
+#include <stdio.h> /* include standard I/O library */
+
+int main(int argc, char *argv[])
+{
+ int sock_fd;
+ int i, nread;
+ struct sockaddr_in serv_add;
+ char buffer[MAXLINE];
+ ...
+ /* create socket */
+ if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("Socket creation error");
+ return -1;
+ }
+ /* initialize address */
+ memset((void *) &serv_add, 0, sizeof(serv_add)); /* clear server address */
+ serv_add.sin_family = AF_INET; /* address type is INET */
+ serv_add.sin_port = htons(13); /* daytime post is 13 */
+ /* build address using inet_pton */
+ if ( (inet_pton(AF_INET, argv[optind], &serv_add.sin_addr)) <= 0) {
+ perror("Address creation error");
+ return -1;
+ }
+ /* extablish connection */
+ if (connect(sock_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) {
+ perror("Connection error");
+ return -1;
+ }
+ /* read daytime from server */
+ while ( (nread = read(sock_fd, buffer, MAXLINE)) > 0) {
+ buffer[nread]=0;
+ if (fputs(buffer, stdout) == EOF) { /* write daytime */
+ perror("fputs error");
+ return -1;
+ }
+ }
+ /* error on read */
+ if (nread < 0) {
+ perror("Read error");
+ return -1;
+ }
+ /* normal exit */
+ return 0;
+}
+ \end{lstlisting}
+ \caption{Esempio di codice di un client elementare per il servizio daytime.}
+ \label{fig:net_cli_code}
+\end{figure}
+
+Il sorgente completo del programma (\file{ElemDaytimeTCPClient.c}, che
+comprende il trattamento delle opzioni e una funzione per stampare un
+messaggio di aiuto) è allegato alla guida nella sezione dei codici sorgente e
+può essere compilato su una qualunque macchina Linux.
+
+Il programma anzitutto include gli header necessari (\texttt{\small 1--5});
+dopo la dichiarazione delle variabili (\texttt{\small 9--12}) si è omessa
+tutta la parte relativa al trattamento degli argomenti passati dalla linea di
+comando (effettuata con le apposite routine illustrate in
+\capref{sec:proc_opt_handling}).
+
+Il primo passo (\texttt{\small 14--18}) è creare un \textit{socket} IPv4
+(\const{AF\_INET}), di tipo TCP \const{SOCK\_STREAM}. La funzione
+\func{socket} ritorna il descrittore che viene usato per identificare il
+socket in tutte le chiamate successive. Nel caso la chiamata fallisca si
+stampa un errore con la relativa routine e si esce.
+
+Il passo seguente (\texttt{\small 19--27}) è quello di costruire un'apposita
+struttura \type{sockaddr\_in} in cui sarà inserito l'indirizzo del server ed
+il numero della porta del servizio. Il primo passo è inizializzare tutto a
+zero, per poi inserire il tipo di protocollo e la porta (usando per
+quest'ultima la funzione \func{htons} per convertire il formato dell'intero
+usato dal computer a quello usato nella rete), infine si utilizza la funzione
+\func{inet\_pton} per convertire l'indirizzo numerico passato dalla linea di
+comando.
+
+Usando la funzione \func{connect} sul socket creato in precedenza
+(\texttt{\small 28--32}) si provvede poi a stabilire la connessione con il
+server specificato dall'indirizzo immesso nella struttura passata come secondo
+argomento, il terzo argomento è la dimensione di detta struttura. Dato che
+esistono diversi tipi di socket, si è dovuto effettuare un cast della
+struttura inizializzata in precedenza, che è specifica per i socket IPv4. Un
+valore di ritorno negativo implica il fallimento della connessione.
+
+Completata con successo la connessione il passo successivo (\texttt{\small
+ 34--40}) è leggere la data dal socket; il server invierà sempre una stringa
+di 26 caratteri della forma \verb|Wed Apr 4 00:53:00 2001\r\n|, che viene
+letta dalla funzione \func{read} e scritta su \file{stdout}.
+
+Dato il funzionamento di TCP la risposta potrà tornare in un unico pacchetto
+di 26 byte (come avverrà senz'altro nel caso in questione) ma potrebbe anche
+arrivare in 26 pacchetti di un byte. Per questo nel caso generale non si può
+mai assumere che tutti i dati arrivino con una singola lettura, pertanto
+quest'ultima deve essere effettuata in un ciclo in cui si continui a leggere
+fintanto che la funzione \func{read} non ritorni uno zero (che significa che
+l'altro capo ha chiuso la connessione) o un numero minore di zero (che
+significa un errore nella connessione).
+
+Si noti come in questo caso la fine dei dati sia specificata dal server che
+chiude la connessione; questa è una delle tecniche possibili (è quella usata
+pure dal protocollo HTTP), ma ce ne possono essere altre, ad esempio FTP marca
+la conclusione di un blocco di dati con la sequenza ASCII \verb|\r\n|
+(carriage return e line feed), mentre il DNS mette la lunghezza in testa ad
+ogni blocco che trasmette. Il punto essenziale è che TCP non provvede nessuna
+indicazione che permetta di marcare dei blocchi di dati, per cui se questo è
+necessario deve provvedere il programma stesso.
+
+\subsection{Un primo esempio di server}
+\label{sec:net_serv_sample}
+
+Dopo aver illustrato il client daremo anche un esempio di un server
+elementare, in grado di rispondere al precedente client. Il listato è
+nuovamente mostrato in \figref{fig:net_serv_code}, il sorgente completo
+(\file{ElemDaytimeTCPServer.c}) è allegato insieme agli altri file nella
+directory \file{sources}.
+
+\begin{figure}[!htbp]
+ \footnotesize
+ \begin{lstlisting}{}
+#include <sys/types.h> /* predefined types */
+#include <unistd.h> /* include unix standard library */
+#include <arpa/inet.h> /* IP addresses conversion utilities */
+#include <sys/socket.h> /* socket library */
+#include <stdio.h> /* include standard I/O library */
+#include <time.h>
+#define MAXLINE 80
+#define BACKLOG 10
+int main(int argc, char *argv[])
+{
+/*
+ * Variables definition
+ */
+ int list_fd, conn_fd;
+ int i;
+ struct sockaddr_in serv_add;
+ char buffer[MAXLINE];
+ time_t timeval;
+ ...
+ /* create socket */
+ if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("Socket creation error");
+ exit(-1);
+ }
+ /* initialize address */
+ memset((void *)&serv_add, 0, sizeof(serv_add)); /* clear server address */
+ serv_add.sin_family = AF_INET; /* address type is INET */
+ serv_add.sin_port = htons(13); /* daytime port is 13 */
+ serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */
+ /* bind socket */
+ if (bind(list_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) {
+ perror("bind error");
+ exit(-1);
+ }
+ /* listen on socket */
+ if (listen(list_fd, BACKLOG) < 0 ) {
+ perror("listen error");
+ exit(-1);
+ }
+ /* write daytime to client */
+ while (1) {
+ if ( (conn_fd = accept(list_fd, (struct sockaddr *) NULL, NULL)) <0 ) {
+ perror("accept error");
+ exit(-1);
+ }
+ timeval = time(NULL);
+ snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&timeval));
+ if ( (write(conn_fd, buffer, strlen(buffer))) < 0 ) {
+ perror("write error");
+ exit(-1);
+ }
+ close(conn_fd);
+ }
+ /* normal exit */
+ exit(0);
+}
+ \end{lstlisting}
+ \caption{Esempio di codice di un semplice server per il servizio daytime.}
+ \label{fig:net_serv_code}
+\end{figure}
+
+Come per il client si includono gli header necessari a cui è aggiunto quello
+per trattare i tempi, e si definiscono alcune costanti e le variabili
+necessarie in seguito (\texttt{\small 1--18}), come nel caso precedente si
+sono omesse le parti relative al trattamento delle opzioni da riga di comando.