Revisione di alcune funzioni e rilettura generale.
[gapil.git] / socket.tex
index 54e7d48662850309a35c522406d298928c910023..687ccc2e9d26737dbc2eec7c169342d50603f3fd 100644 (file)
@@ -560,7 +560,7 @@ cosa significa tutto ci
 utile anche in seguito.
 
 
-\subsection{La \textit{endianess}}
+\subsection{La \textit{endianess}\index{endianess}}
 \label{sec:sock_endianess}
 
 La rappresentazione di un numero binario in un computer può essere fatta in
@@ -579,12 +579,12 @@ significativi nell'indirizzo successivo; questo ordinamento 
 numero. Il caso opposto, in cui si parte dal bit meno significativo è detto
 per lo stesso motivo \textit{big endian}.
 
-La \textit{endianess} di un computer dipende essenzialmente dalla architettura
-hardware usata; Intel e Digital usano il \textit{little endian}, Motorola,
-IBM, Sun (sostanzialmente tutti gli altri) usano il \textit{big endian}. Il
-formato della rete è anch'esso \textit{big endian}, altri esempi sono quello
-del bus PC, che è \textit{little endian}, o quello del bus VME che è
-\textit{big endian}.
+La \textit{endianess}\index{endianess} di un computer dipende essenzialmente
+dalla architettura hardware usata; Intel e Digital usano il \textit{little
+  endian}, Motorola, IBM, Sun (sostanzialmente tutti gli altri) usano il
+\textit{big endian}. Il formato della rete è anch'esso \textit{big endian},
+altri esempi sono quello del bus PCI, che è \textit{little endian}, o quello
+del bus VME che è \textit{big endian}.
 
 Esistono poi anche dei processori che possono scegliere il tipo di formato
 all'avvio e alcuni che, come il PowerPC o l'Intel i860, possono pure passare
@@ -596,11 +596,12 @@ questi cambiamenti.
 \subsection{Le funzioni per il riordinamento}
 \label{sec:sock_func_ord}
 
-Il problema connesso all'endianess è che quando si passano dei dati da un tipo
-di architettura all'altra i dati vengono interpretati in maniera diversa, e ad
-esempio nel caso dell'intero a 16 bit ci si ritroverà con i due byte in cui è
-suddiviso scambiati di posto, e ne sarà quindi invertito l'ordine di lettura
-per cui, per riavere il valore originale dovranno essere rovesciati.
+Il problema connesso all'endianess\index{endianess} è che quando si passano
+dei dati da un tipo di architettura all'altra i dati vengono interpretati in
+maniera diversa, e ad esempio nel caso dell'intero a 16 bit ci si ritroverà
+con i due byte in cui è suddiviso scambiati di posto, e ne sarà quindi
+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
@@ -647,8 +648,8 @@ assicurare la portabilit
 \label{sec:sock_func_ipv4}
 
 Un secondo insieme di funzioni di manipolazione serve per passare dal formato
-binario usato nelle strutture degli indirizzi alla rappresentazione dei numeri
-IP che si usa normalmente.
+binario usato nelle strutture degli indirizzi alla rappresentazione simbolica
+dei numeri IP che si usa normalmente.
 
 Le prime tre funzioni di manipolazione riguardano la conversione degli
 indirizzi IPv4 da una stringa in cui il numero di IP è espresso secondo la
@@ -656,29 +657,44 @@ cosiddetta notazione \textit{dotted-decimal}, (cio
 \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:
-\begin{prototype}{arpa/inet.h}
-  {int inet\_aton(const char *src, struct in\_addr *dest)} 
-  Converte la stringa puntata da \var{src} nell'indirizzo binario da
-  memorizzare all'indirizzo puntato da \var{dest}, restituendo 0 in caso di
-  successo e 1 in caso di fallimento (è espressa in questa forma in modo da
-  poterla usare direttamente con il puntatore usato per passare la struttura
-  degli indirizzi). Se usata con \var{dest} inizializzato a \val{NULL}
-  effettua la validazione dell'indirizzo.
-\end{prototype}
-\begin{prototype}{arpa/inet.h}{in\_addr\_t inet\_addr(const char *strptr)}
-  Restituisce l'indirizzo a 32 bit in network order a partire dalla stringa
-  passata come parametro, in caso di errore restituisce il valore
-  \const{INADDR\_NONE} che tipicamente sono trentadue bit a uno; questo
-  comporta che la stringa \texttt{255.255.255.255}, che pure è un indirizzo
-  valido, non può essere usata con questa funzione; per questo motivo essa è
-  generalmente deprecata in favore della precedente.
-\end{prototype}  
-\begin{prototype}{arpa/inet.h}{char *inet\_ntoa(struct in\_addr addrptr)}
-  Converte il valore a 32 bit dell'indirizzo (espresso in \textit{network
-    order}) restituendo il puntatore alla stringa che contiene l'espressione
-  in formato dotted decimal. Si deve tenere presente che la stringa risiede in
-  memoria statica, per cui questa funzione non è rientrante.
-\end{prototype}
+\begin{functions}
+  \headdecl{arpa/inet.h}
+  
+  \funcdecl{in\_addr\_t inet\_addr(const char *strptr)} Converte la stringa
+  dell'indirizzo \textit{dotted decimal} in nel numero IP in network order.
+
+  \funcdecl{int inet\_aton(const char *src, struct in\_addr *dest)} Converte
+  la stringa dell'indirizzo \textit{dotted decimal} in un indirizzo IP.
+
+  \funcdecl{char *inet\_ntoa(struct in\_addr addrptr)}
+  Converte un indirizzo IP in una stringa \textit{dotted decimal}.
+
+  \bodydesc{Tutte queste le funzioni non generano codice di errore.}
+\end{functions}
+
+La prima funcione, \func{inet\_addr}, restituisce l'indirizzo a 32 bit in
+network order (del tipo \type{in\_addr\_t}) a partire dalla stringa passata
+nellargomento \param{strptr}. In caso di errore (quando la stringa non esprime
+un indirizzo valido) restituisce invece il valore \const{INADDR\_NONE} che
+tipicamente sono trentadue bit a uno.  Questo però comporta che la stringa
+\texttt{255.255.255.255}, che pure è un indirizzo valido, non può essere usata
+con questa funzione; per questo motivo essa è generalmente deprecata in favore
+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
+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}
+effettua la validazione dell'indirizzo.
+
+L'ultima funzione, \func{inet\_ntoa}, converte il valore a 32 bit
+dell'indirizzo (espresso in \textit{network order}) restituendo il puntatore
+alla stringa che contiene l'espressione in formato dotted decimal. Si deve
+tenere presente che la stringa risiede in memoria statica, per cui questa
+funzione non è rientrante.
 
 
 \subsection{Le funzioni \func{inet\_pton} e \func{inet\_ntop}}
@@ -709,7 +725,7 @@ prototipi delle suddette funzioni sono i seguenti:
   Converte l'indirizzo espresso tramite una stringa nel valore numerico.
   
   \bodydesc{La funzione restituisce un valore negativo se \var{af} specifica
-    una famiglia di indirizzi non valida, settando \var{errno} a
+    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.}
 \end{prototype}
@@ -724,21 +740,26 @@ indirizzi non valida.
 
 \begin{prototype}{sys/socket.h}
   {char *inet\_ntop(int af, const void *addr\_ptr, char *dest, size\_t len)}
-  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}.
+  Converte l'indirizzo dalla relativa struttura in una stringa simbolica.
  
-  \bodydesc{La funzione restituisce un puntatore non nullo a \var{dest} in
-    caso di successo e un puntatore nullo in caso di fallimento, in
-    quest'ultimo caso viene impostata la variabile \var{errno} con il valore
-    \errval{ENOSPC} in caso le dimensioni dell'indirizzo eccedano la lunghezza
-    specificata da \var{len} o \errval{ENOAFSUPPORT} in caso \var{af} non sia
-    una famiglia di indirizzi valida.}
+  \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
@@ -746,7 +767,7 @@ devono essere precedentemente allocate e passate attraverso il puntatore
 nullo e deve essere allocato precedentemente.
 
 Il formato usato per gli indirizzi in formato di presentazione è la notazione
-\textit{dotted decimal} per IPv4 e quella descritta in
+\textit{dotted decimal} per IPv4 e quello descritto in
 \secref{sec:IP_ipv6_notation} per IPv6.
 
 
@@ -756,8 +777,9 @@ Il formato usato per gli indirizzi in formato di presentazione 
 
 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, esamineremo una caratteristica
-delle funzioni di I/O sui socket che ci tornerà utile anche in seguito.
+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}
@@ -771,13 +793,15 @@ 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 anche per l'I/O su file, e succede
-perché si eccede in lettura o scrittura il limite di buffer del kernel.
+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 (lo stesso può
-avvenire scrivendo più di 4096 byte in una pipe, dato che quello è il limite
-di solito adottato per il buffer di trasmissione del kernel).
+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
@@ -811,11 +835,11 @@ ssize_t SockRead(int fd, void *buf, size_t count)
   \label{fig:sock_SockRead_code}
 \end{figure}
 
-Per questo motivo seguendo l'esempio di W. R. Stevens 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
+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}.
 
@@ -856,8 +880,9 @@ 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 e pertanto si ritorna senza aver concluso la
-lettura di tutti i byte richiesti.
+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.