-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 \nfig\ è 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
-(\macro{AF\_INET}), di tipo TCP \macro{SOCK\_STREAM}. La funzione
-\macro{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 una 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 \nfig, 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.
-
-La creazione del socket (\texttt{\small 22--26}) è analoga al caso precedente,
-come pure l'inizializzazione della struttura \type{sockaddr\_in}, anche in
-questo caso si usa la porta standard del servizio daytime, ma come indirizzo
-IP si il valore predefinito \macro{INET\_ANY} che corrisponde ad un indirizzo
-generico (\texttt{\small 27--31}).
-
-Si effettua poi (\texttt{\small 32--36}) la chiamata alla funzione
-\func{bind} che permette di associare la precedente struttura al socket, in
-modo che quest'ultimo possa essere usato per accettare connessioni su una
-qualunque delle interfacce di rete locali.
-
-Il passo successivo (\texttt{\small 37--41}) è mettere ``in ascolto'' il
-socket, questo viene effettuato con la funzione \func{listen} che dice al
-kernel di accettare connessioni per il socket specificato, la funzione indica
-inoltre, con il secondo parametro, il numero massimo di connessioni che il
-kernel accetterà di mettere in coda per il suddetto socket.
-
-Questa ultima chiamata completa la preparazione del socket per l'ascolto (che
-viene chiamato anche \textit{listening descriptor}) a questo punto il processo
-è mandato in sleep (\texttt{\small 44--47}) con la successiva chiamata alla
-funzione \func{accept}, fin quando non arriva e viene accettata una
-connessione da un client.
-
-Quando questo avviene \func{accept} ritorna un secondo descrittore di socket,
-che viene chiamato \textit{connected descriptor} che è quello che viene usato
-dalla successiva chiamata alla \func{write} per scrivere la risposta al
-client, una volta che si è opportunamente (\texttt{\small 48--49}) costruita
-la stringa con la data da trasmettere. Completata la trasmissione il nuovo
-socket viene chiuso (\texttt{\small 54}). Il tutto è inserito in un ciclo
-infinito (\texttt{\small 42--55}) in modo da poter ripetere l'invio della data
-ad una successiva connessione.
-
-È importante notare che questo server è estremamente elementare, infatti a
-parte il fatto di essere dipendente da IPv4, esso è in grado di servire solo
-un client alla volta, è cioè un \textsl{server iterativo}, inoltre esso è
-scritto per essere lanciato da linea di comando, se lo si volesse utilizzare
-come demone di sistema (che è in esecuzione anche quando non c'è nessuna shell
-attiva e il terminale da cui lo si è lanciato è stato sconnesso),
-occorrerebbero delle opportune modifiche.
+Gli indirizzi vengono convertiti da/alle rispettive strutture di indirizzo
+(una struttura \struct{in\_addr} per IPv4, e una struttura \struct{in6\_addr}
+per IPv6), che devono essere precedentemente allocate e passate attraverso il
+puntatore \param{addr\_ptr}; l'argomento \param{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
+sez.~\ref{sec:IP_ipv6_notation} per IPv6.
+
+\index{socket!definizione|)}
+
+
+
+
+
+
+
+% LocalWords: socket sez cap BSD SVr XTI Transport Interface TCP stream UDP PF
+% LocalWords: datagram broadcast descriptor sys int domain type protocol errno
+% LocalWords: EPROTONOSUPPORT ENFILE kernel EMFILE EACCES EINVAL ENOBUFS raw
+% LocalWords: ENOMEM table family AF address name glibc UNSPEC LOCAL Local IPv
+% LocalWords: communication INET protocols ip AX Amateur IPX Novell APPLETALK
+% LocalWords: Appletalk ddp NETROM NetROM Multiprotocol ATMPVC Access to ATM
+% LocalWords: PVCs ITU ipv PLP DECnet Reserved for project NETBEUI LLC KEY key
+% LocalWords: SECURITY Security callback NETLINK interface device netlink Low
+% LocalWords: PACKET level packet ASH Ash ECONET Acorn Econet ATMSVC SVCs SNA
+% LocalWords: IRDA PPPOX PPPoX WANPIPE Wanpipe BLUETOOTH Bluetooth POSIX bits
+% LocalWords: dall'header tab SOCK capabilities capability styles DGRAM read
+% LocalWords: SEQPACKET RDM sockaddr reference void fig Header uint socklen at
+% LocalWords: addr netinet port len Stevens unsigned short casting nell'header
+% LocalWords: BIND SERVICE bind union order big endian flowinfo dell'header ll
+% LocalWords: multicast multicasting local socketpair sun path filesystem AARP
+% LocalWords: pathname AppleTalk netatalk personal Apple ATPROTO atalk sat if
+% LocalWords: ANYNET node ANYNODE ATADDR BCAST pcap IEEE linux ether ETH ALL
+% LocalWords: sll ifindex ethernet halen MAC hatype ARP arp pkttype HOST recv
+% LocalWords: OTHERHOST OUTGOING recvfrom recvmsg endianness little endtest Mac
+% LocalWords: Intel Digital Motorola IBM VME PowerPC l'Intel xABCD ptr htonl
+% LocalWords: htons ntohl ntohs long hostlong hostshort netlong
+% LocalWords: sort netshort host inet aton ntoa dotted decimal const char src
+% LocalWords: strptr struct dest addrptr INADDR NULL pton ntop presentation af
+% LocalWords: numeric EAFNOSUPPORT size ENOSPC ENOAFSUPPORT ADDRSTRLEN ROUTE
+% LocalWords: of tcpdump page
+
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: