X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=socket.tex;h=43c4905d1d4f23d82328c70975fa486ca307d835;hp=687ccc2e9d26737dbc2eec7c169342d50603f3fd;hb=da0899b61653d07d75c8df134906261f1afd2485;hpb=df52b4351217a5ca93506df97a34f6fba69474f0 diff --git a/socket.tex b/socket.tex index 687ccc2..43c4905 100644 --- a/socket.tex +++ b/socket.tex @@ -27,6 +27,8 @@ concluderemo il capitolo con un primo esempio di applicazione. Iniziamo con una descrizione essenziale di cosa sono i \textit{socket} e di quali sono i concetti fondamentali da tenere presente quando si ha a che fare con essi. +\index{socket|(} + \subsection{I \textit{socket}} \label{sec:sock_socket_def} @@ -108,7 +110,7 @@ il tipo di comunicazione che esso deve utilizzare. \label{sec:sock_socket} La creazione di un socket avviene attraverso l'uso della funzione -\func{socket}; questa restituisce un \textit{file descriptor}\footnote{del +\funcd{socket}; questa restituisce un \textit{file descriptor}\footnote{del tutto analogo a quelli che si ottengono per i file di dati e le pipe, descritti in \secref{sec:file_fd}.} che serve come riferimento al socket; il suo protototipo è: @@ -316,7 +318,7 @@ nelle varie famiglie di protocolli; questo pone il problema di come passare questi puntatori, il C ANSI risolve questo problema coi i puntatori generici (i \ctyp{void *}), ma l'interfaccia dei socket è antecedente alla definizione dello standard ANSI, e per questo nel 1982 fu scelto di definire una struttura -generica per gli indirizzi dei socket, \type{sockaddr}, che si è riportata in +generica per gli indirizzi dei socket, \struct{sockaddr}, che si è riportata in \figref{fig:sock_sa_gen_struct}. \begin{figure}[!htb] @@ -329,7 +331,8 @@ struct sockaddr { }; \end{lstlisting} \end{minipage} - \caption{La struttura generica degli indirizzi dei socket \type{sockaddr}} + \caption{La struttura generica degli indirizzi dei socket + \structd{sockaddr}.} \label{fig:sock_sa_gen_struct} \end{figure} @@ -376,7 +379,7 @@ include in cui sono definiti; la struttura \end{table} In alcuni sistemi la struttura è leggermente diversa e prevede un primo membro -aggiuntivo \var{uint8\_t sin\_len} (come riportato da R. Stevens nei suoi +aggiuntivo \code{uint8\_t sin\_len} (come riportato da R. Stevens nei suoi libri). Questo campo non verrebbe usato direttamente dal programmatore e non è richiesto dallo standard POSIX.1g, in Linux pertanto non esiste. Il campo \type{sa\_family\_t} era storicamente un \ctyp{unsigned short}. @@ -395,7 +398,7 @@ l'uso di questa struttura. I socket di tipo \const{PF\_INET} vengono usati per la comunicazione attraverso internet; la struttura per gli indirizzi per un socket internet -(IPv4) è definita come \type{sockaddr\_in} nell'header file +(IPv4) è definita come \struct{sockaddr\_in} nell'header file \file{netinet/in.h} e secondo le pagine di manuale ha la forma mostrata in \figref{fig:sock_sa_ipv4_struct}, conforme allo standard POSIX.1g. @@ -415,7 +418,7 @@ struct in_addr { \end{lstlisting} \end{minipage} \caption{La struttura degli indirizzi dei socket internet (IPv4) - \type{sockaddr\_in}.} + \structd{sockaddr\_in}.} \label{fig:sock_sa_ipv4_struct} \end{figure} @@ -435,7 +438,7 @@ possono usare la funzione \func{bind} su queste porte. Il membro \var{sin\_addr} contiene l'indirizzo internet dell'altro capo della comunicazione, e viene acceduto sia come struttura (un resto di una -implementazione precedente in cui questa era una \texttt{union} usata per +implementazione precedente in cui questa era una \direct{union} usata per accedere alle diverse classi di indirizzi) che come intero. Infine è da sottolineare che sia gli indirizzi che i numeri di porta devono @@ -472,7 +475,7 @@ struct in6_addr { \end{lstlisting} \end{minipage} \caption{La struttura degli indirizzi dei socket IPv6 - \type{sockaddr\_in6}.} + \structd{sockaddr\_in6}.} \label{fig:sock_sa_ipv6_struct} \end{figure} @@ -488,7 +491,7 @@ Il campo \var{sin6\_addr} contiene l'indirizzo a 128 bit usato da IPv6, infine il campo \var{sin6\_scope\_id} è un campo introdotto con il kernel 2.4 per gestire alcune operazioni riguardanti il multicasting. -Si noti che questa struttura è più grande di una \var{sockaddr} generica, +Si noti che questa struttura è più grande di una \struct{sockaddr} generica, quindi occorre stare attenti a non avere fatto assunzioni riguardo alla possibilità di contenere i dati nelle dimensioni di quest'ultima. @@ -516,7 +519,7 @@ struct sockaddr_un { \end{lstlisting} \end{minipage} \caption{La struttura degli indirizzi dei socket locali - \var{sockaddr\_un}.} + \structd{sockaddr\_un}.} \label{fig:sock_sa_local_struct} \end{figure} @@ -603,26 +606,27 @@ con i due byte in cui invertito l'ordine di lettura per cui, per riavere il valore originale dovranno essere rovesciati. -Per questo motivo si usano le seguenti funzioni di conversione che servono a -tener conto automaticamente della possibile differenza fra l'ordinamento usato -sul computer e quello che viene usato nelle trasmissione sulla rete; queste -funzioni sono: +Per questo motivo si usano delle funzioni di conversione che servono a tener +conto automaticamente della possibile differenza fra l'ordinamento usato sul +computer e quello che viene usato nelle trasmissione sulla rete; queste +funzioni sono \funcd{htonl}, \funcd{htons}, \funcd{ntonl} e \funcd{ntons} ed i +rispettivi prototipi sono: \begin{functions} \headdecl{netinet/in.h} \funcdecl{unsigned long int htonl(unsigned long int hostlong)} - Converte l'intero a 32 bit \var{hostlong} dal formato della macchina a + Converte l'intero a 32 bit \param{hostlong} dal formato della macchina a quello della rete. \funcdecl{unsigned short int htons(unsigned short int hostshort)} - Converte l'intero a 16 bit \var{hostshort} dal formato della macchina a + Converte l'intero a 16 bit \param{hostshort} dal formato della macchina a quello della rete. \funcdecl{unsigned long int ntonl(unsigned long int netlong)} - Converte l'intero a 32 bit \var{netlong} dal formato della rete a quello + Converte l'intero a 32 bit \param{netlong} dal formato della rete a quello della macchina. \funcdecl{unsigned sort int ntons(unsigned short int netshort)} - Converte l'intero a 16 bit \var{netshort} dal formato della rete a quello + Converte l'intero a 16 bit \param{netshort} dal formato della rete a quello della macchina. \bodydesc{Tutte le funzioni restituiscono il valore convertito, e non hanno @@ -656,7 +660,8 @@ indirizzi IPv4 da una stringa in cui il numero di IP cosiddetta notazione \textit{dotted-decimal}, (cioè nella forma \texttt{192.160.0.1}) al formato binario (direttamente in \textit{network order}) e viceversa; in questo caso si usa la lettera \texttt{a} come -mnemonico per indicare la stringa. Dette funzioni sono: +mnemonico per indicare la stringa. Dette funzioni sono \funcd{inet\_addr}, +\funcd{inet\_aton} e \funcd{inet\_ntoa}, ed i rispettivi prototipi sono: \begin{functions} \headdecl{arpa/inet.h} @@ -683,11 +688,11 @@ di \func{inet\_aton}. La funzione \func{inet\_aton} converte la stringa puntata da \param{src} nell'indirizzo binario che viene memorizzato nell'opportuna struttura -\var{in\_addr} (si veda \secref{fig:sock_sa_ipv4_struct}) situata +\struct{in\_addr} (si veda \secref{fig:sock_sa_ipv4_struct}) situata all'indirizzo dato dall'argomento \param{dest} (è espressa in questa forma in modo da poterla usare direttamente con il puntatore usato per passare la struttura degli indirizzi). La funzione restituesce 0 in caso di successo e 1 -in caso di fallimento. Se usata con \var{dest} inizializzato a \val{NULL} +in caso di fallimento. Se usata con \param{dest} inizializzato a \val{NULL} effettua la validazione dell'indirizzo. L'ultima funzione, \func{inet\_ntoa}, converte il valore a 32 bit @@ -717,14 +722,15 @@ e \textit{numeric}. % \end{figure} Entrambe le funzioni accettano l'argomento \param{af} che indica il tipo di -indirizzo e può essere soltanto \const{AF\_INET} o \const{AF\_INET6}. I -prototipi delle suddette funzioni sono i seguenti: +indirizzo e può essere soltanto \const{AF\_INET} o \const{AF\_INET6}. La prima +funzione è \funcd{inet\_pton}, che serve a convertire una stringa in un +indirizzo, il suo prototipo è: \begin{prototype}{sys/socket.h} {int inet\_pton(int af, const char *src, void *addr\_ptr)} Converte l'indirizzo espresso tramite una stringa nel valore numerico. - \bodydesc{La funzione restituisce un valore negativo se \var{af} specifica + \bodydesc{La funzione restituisce un valore negativo se \param{af} specifica una famiglia di indirizzi non valida, con \var{errno} che assume il valore \errcode{EAFNOSUPPORT}, un valore nullo se \param{src} non rappresenta un indirizzo valido, ed un valore positivo in caso di successo.} @@ -732,12 +738,13 @@ prototipi delle suddette funzioni sono i seguenti: La funzione converte la stringa indicata tramite \param{src} nel valore numerico dell'indirizzo IP del tipo specificato da \param{af} che viene -memorizzato all'indirizzo puntato da \var{addr\_ptr}, la funzione restituisce +memorizzato all'indirizzo puntato da \param{addr\_ptr}, la funzione restituisce un valore positivo in caso di successo, e zero se la stringa non rappresenta -un indirizzo valido, e negativo se \var{af} specifica una famiglia di +un indirizzo valido, e negativo se \param{af} specifica una famiglia di indirizzi non valida. - +La sedonda funzione è \funcd{inet\_ntop} che converte un indirizzo in una +stringa; il suo prototipo è: \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. @@ -747,29 +754,30 @@ indirizzi non valida. 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. + dell'indirizzo eccedono la lunghezza specificata da \param{len}. + \item[\errcode{ENOAFSUPPORT}] la famiglia di indirizzi \param{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}. +La funzione converte la struttura dell'indirizzo puntata da \param{addr\_ptr} +in una stringa che viene copiata nel buffer puntato dall'indirizzo +\param{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 \param{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. +(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 \secref{sec:IP_ipv6_notation} per IPv6. +\index{socket|)} \section{Un esempio di applicazione} @@ -869,7 +877,7 @@ ssize_t SockWrite(int fd, const void *buf, size_t count) return (count); } \end{lstlisting} - \caption{Funzione \func{SockWrite}, scrive \var{count} byte su un socket } + \caption{Funzione \func{SockWrite}, scrive \var{count} byte su un socket.} \label{fig:sock_SockWrite_code} \end{figure} @@ -970,12 +978,12 @@ comando (effettuata con le apposite routine illustrate in Il primo passo (\texttt{\small 14--18}) è creare un \textit{socket} IPv4 (\const{AF\_INET}), di tipo TCP \const{SOCK\_STREAM}. La funzione -\const{socket} ritorna il descrittore che viene usato per identificare il +\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 +struttura \struct{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 @@ -1093,7 +1101,7 @@ 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 +come pure l'inizializzazione della struttura \struct{sockaddr\_in}, anche in questo caso si usa la porta standard del servizio daytime, ma come indirizzo IP si il valore predefinito \const{INET\_ANY} che corrisponde ad un indirizzo generico (\texttt{\small 27--31}). @@ -1132,6 +1140,8 @@ come demone di sistema (che attiva e il terminale da cui lo si è lanciato è stato sconnesso), occorrerebbero delle opportune modifiche. + + %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil"