%% socket.tex
%%
-%% Copyright (C) 2000-2002 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2005 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
-%% Free Software Foundation; with the Invariant Sections being "Prefazione",
+%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
%% with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the
%% license is included in the section entitled "GNU Free Documentation
%% License".
In questo capitolo inizieremo a spiegare le caratteristiche salienti della
principale interfaccia per la programmazione di rete, quella dei
-\textit{socket}, che, pur essendo nata in ambiente Unix è usata ormai da tutti
-i sistemi operativi.
+\textit{socket}, che, pur essendo nata in ambiente Unix, è usata ormai da
+tutti i sistemi operativi.
Dopo una breve panoramica sulle caratteristiche di questa interfaccia vedremo
come creare un socket e come collegarlo allo specifico protocollo di rete che
\textsl{presa}, ma essendo universalmente noti come \textit{socket}
utilizzeremo sempre la parola inglese.} sono uno dei principali meccanismi
di comunicazione utilizzato in ambito Unix, e li abbiamo brevemente incontrati
-in \secref{sec:ipc_socketpair}, fra i vari meccanismi di intercominazione fra
-processi. Un socket costituisce in sostanza un canale di comunicazione fra due
-processi su cui si possono leggere e scrivere dati analogo a quello di una
-pipe (vedi \secref{sec:ipc_pipes}) ma, a differenza di questa e degli altri
-meccanismi esaminati nel capitolo \capref{cha:IPC}, i socket non sono limitati
-alla comunicazione fra processi che girano sulla stessa macchina, ma possono
-realizzare la comunicazione anche attraverso la rete.
+in sez.~\ref{sec:ipc_socketpair}, fra i vari meccanismi di intercominazione
+fra processi. Un socket costituisce in sostanza un canale di comunicazione fra
+due processi su cui si possono leggere e scrivere dati analogo a quello di una
+pipe (vedi sez.~\ref{sec:ipc_pipes}) ma, a differenza di questa e degli altri
+meccanismi esaminati nel capitolo cap.~\ref{cha:IPC}, i socket non sono
+limitati alla comunicazione fra processi che girano sulla stessa macchina, ma
+possono realizzare la comunicazione anche attraverso la rete.
Quella dei socket costituisce infatti la principale interfaccia usata nella
programmazione di rete. La loro origine risale al 1983, quando furono
\label{sec:sock_gen}
Per capire il funzionamento dei socket occorre avere presente il funzionamento
-dei protocolli di rete (vedi \capref{cha:network}), ma l'interfaccia è del
+dei protocolli di rete (vedi cap.~\ref{cha:network}), ma l'interfaccia è del
tutto generale e benché le problematiche (e quindi le modalità di risolvere i
problemi) siano diverse a seconda del tipo di protocollo di comunicazione
usato, le funzioni da usare restano le stesse.
avviene, in certi casi essa può essere condotta con una connessione diretta
con un solo corrispondente, come per una telefonata; altri casi possono
prevedere una comunicazione come per lettera, in cui si scrive l'indirizzo su
-ogni pacchetto, altri ancora una comunicazione \textit{broadcast} come per la
-radio, in cui i pacchetti vengono emessi su appositi ``\textsl{canali}'' dove
-chiunque si collega possa riceverli.
+ogni pacchetto, altri ancora una comunicazione \itindex{broadcast}
+\textit{broadcast} come per la radio, in cui i pacchetti vengono emessi su
+appositi ``\textsl{canali}'' dove chiunque si collega possa riceverli.
É chiaro che ciascuno di questi stili comporta una modalità diversa di gestire
la comunicazione, ad esempio se è inaffidabile occorrerà essere in grado di
La creazione di un socket avviene attraverso l'uso della funzione
\funcd{socket}; essa 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 prototipo è:
+ descritti in sez.~\ref{sec:file_fd}.} che serve come riferimento al socket;
+il suo prototipo è:
\begin{prototype}{sys/socket.h}{int socket(int domain, int type, int protocol)}
Apre un socket.
\end{prototype}
La funzione ha tre argomenti, \param{domain} specifica il dominio del socket
-(definisce cioè, come vedremo in \secref{sec:sock_domain}, la famiglia di
+(definisce cioè, come vedremo in sez.~\ref{sec:sock_domain}, la famiglia di
protocolli usata), \param{type} specifica il tipo di socket (definisce cioè,
-come vedremo in \secref{sec:sock_type}, lo stile di comunicazione) e
+come vedremo in sez.~\ref{sec:sock_type}, lo stile di comunicazione) e
\param{protocol} il protocollo; in genere quest'ultimo è indicato
implicitamente dal tipo di socket, per cui di norma questo valore viene messo
a zero (con l'eccezione dei \textit{raw socket}).
lo stesso nome.}
I domini (e i relativi nomi simbolici), così come i nomi delle famiglie di
-indirizzi, sono definiti dall'header \textit{socket.h}. Un elenco delle
+indirizzi, sono definiti dall'header \texttt{socket.h}. Un elenco delle
famiglie di protocolli disponibili in Linux è riportato in
-\tabref{tab:net_pf_names}.\footnote{l'elenco indica tutti i protocolli
+tab.~\ref{tab:net_pf_names}.\footnote{l'elenco indica tutti i protocolli
definiti; fra questi però saranno utilizzabili solo quelli per i quali si è
compilato il supporto nel kernel (o si sono caricati gli opportuni moduli),
viene definita anche una costante \const{PF\_MAX} che indica il valore
dall'utente generico, ad esempio in generale tutti i socket di tipo
\const{SOCK\_RAW} possono essere creati solo da processi che hanno i privilegi
di amministratore (cioè con user-ID effettivo uguale a zero) o dotati della
-capability \texttt{CAP\_NET\_RAW}.
+\itindex{capabilities}\textit{capability} \const{CAP\_NET\_RAW}.
\subsection{Il tipo, o stile}
della \acr{glibc} \cite{glibc} chiama \textit{styles}) identificati dalle
seguenti costanti:
-\begin{basedescript}{\desclabelwidth{2.8cm}\desclabelstyle{\nextlinelabel}}
+\begin{basedescript}{\desclabelwidth{2.9cm}\desclabelstyle{\nextlinelabel}}
\item[\const{SOCK\_STREAM}] Provvede un canale di trasmissione dati
bidirezionale, sequenziale e affidabile. Opera su una connessione con un
altro socket. I dati vengono ricevuti e trasmessi come un flusso continuo di
byte (da cui il nome \textit{stream}).
\item[\const{SOCK\_DGRAM}] Viene usato per trasmettere pacchetti di dati
- (\textit{datagram}) di lunghezza massima fissata indirizzati singolarmente,
- Non esiste una connessione e la trasmissione è effettuata in maniera non
- affidabile.
+ (\textit{datagram}) di lunghezza massima prefissata, indirizzati
+ singolarmente. Non esiste una connessione e la trasmissione è effettuata in
+ maniera non affidabile.
\item[\const{SOCK\_SEQPACKET}] Provvede un canale di trasmissione di dati
bidirezionale, sequenziale e affidabile. Opera su una connessione con un
altro socket. I dati possono vengono trasmessi per pacchetti di dimensione
\label{tab:sock_sock_valid_combinations}
\end{table}
-In \secref{tab:sock_sock_valid_combinations} sono mostrate le combinazioni
+In tab.~\ref{tab:sock_sock_valid_combinations} sono mostrate le combinazioni
valide possibili per le principali famiglie di protocolli. Per ogni
combinazione valida si è indicato il tipo di protocollo, o la parola
\textsl{si} qualora non il protocollo non abbia un nome definito, mentre si
generici (i \ctyp{void *}), ma l'interfaccia dei socket è antecedente alla
definizione dello standard ANSI C, e per questo nel 1982 fu scelto di definire
una struttura generica per gli indirizzi dei socket, \struct{sockaddr}, che si
-è riportata in \figref{fig:sock_sa_gen_struct}.
+è riportata in fig.~\ref{fig:sock_sa_gen_struct}.
\begin{figure}[!htb]
\footnotesize \centering
occorrerà eseguire una conversione del relativo puntatore.
I tipi di dati che compongono la struttura sono stabiliti dallo standard
-POSIX.1g e li abbiamo riassunti in \tabref{tab:sock_data_types} con i
+POSIX.1g e li abbiamo riassunti in tab.~\ref{tab:sock_data_types} con i
rispettivi file di include in cui sono definiti; la struttura è invece
definita nell'include file \file{sys/socket.h}.
attraverso internet; la struttura per gli indirizzi per un socket internet (se
si usa IPv4) è definita come \struct{sockaddr\_in} nell'header file
\file{netinet/in.h} ed ha la forma mostrata in
-\figref{fig:sock_sa_ipv4_struct}, conforme allo standard POSIX.1g.
+fig.~\ref{fig:sock_sa_ipv4_struct}, conforme allo standard POSIX.1g.
\begin{figure}[!htb]
\footnotesize\centering
\begin{minipage}[c]{15cm}
\includestruct{listati/sockaddr_in.h}
\end{minipage}
- \caption{La struttura degli indirizzi dei socket internet (IPv4)
- \structd{sockaddr\_in}.}
+ \caption{La struttura \structd{sockaddr\_in} degli indirizzi dei socket
+ internet (IPv4) e la struttura \structd{in\_addr} degli indirizzi IPv4.}
\label{fig:sock_sa_ipv4_struct}
\end{figure}
L'indirizzo di un socket internet (secondo IPv4) comprende l'indirizzo
internet di un'interfaccia più un \textsl{numero di porta} (affronteremo in
-dettaglio il significato di questi numeri in \secref{sec:TCP_port_num}). Il
+dettaglio il significato di questi numeri in sez.~\ref{sec:TCP_port_num}). Il
protocollo IP non prevede numeri di porta, che sono utilizzati solo dai
protocolli di livello superiore come TCP e UDP. Questa struttura però viene
usata anche per i socket RAW che accedono direttamente al livello di IP, nel
specifica il \textsl{numero di porta}. I numeri di porta sotto il 1024 sono
chiamati \textsl{riservati} in quanto utilizzati da servizi standard e
soltanto processi con i privilegi di amministratore (con user-ID effettivo
-uguale a zero) o con la capability \texttt{CAP\_NET\_BIND\_SERVICE} possono
-usare la funzione \func{bind} (che vedremo in \secref{sec:TCP_func_bind}) su
-queste porte.
+uguale a zero) o con la \itindex{capabilities}\textit{capability}
+\const{CAP\_NET\_BIND\_SERVICE} possono usare la funzione \func{bind} (che
+vedremo in sez.~\ref{sec:TCP_func_bind}) su queste porte.
Il membro \var{sin\_addr} contiene un indirizzo internet, e viene acceduto sia
come struttura (un resto di una implementazione precedente in cui questa era
una \direct{union} usata per accedere alle diverse classi di indirizzi) che
direttamente come intero. In \file{netinet/in.h} vengono definite anche alcune
costanti che identificano alcuni indirizzi speciali, riportati in
-\tabref{tab:TCP_ipv4_addr}.
+tab.~\ref{tab:TCP_ipv4_addr}, che reincontreremo più avanti.
Infine occorre sottolineare che sia gli indirizzi che i numeri di porta devono
essere specificati in quello che viene chiamato \textit{network order}, cioè
con i bit ordinati in formato \textit{big endian}, questo comporta la
necessità di usare apposite funzioni di conversione per mantenere la
-portabilità del codice (vedi \secref{sec:sock_addr_func} per i dettagli del
+portabilità del codice (vedi sez.~\ref{sec:sock_addr_func} per i dettagli del
problema e le relative soluzioni).
sostanzialmente identici ai precedenti; la parte in cui si trovano
praticamente tutte le differenze fra i due socket è quella della struttura
degli indirizzi; la sua definizione, presa da \file{netinet/in.h}, è riportata
-in \figref{fig:sock_sa_ipv6_struct}.
+in fig.~\ref{fig:sock_sa_ipv6_struct}.
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
\includestruct{listati/sockaddr_in6.h}
\end{minipage}
- \caption{La struttura degli indirizzi dei socket IPv6
- \structd{sockaddr\_in6}.}
+ \caption{La struttura \structd{sockaddr\_in6} degli indirizzi dei socket
+ IPv6 e la struttura \structd{in6\_addr} degli indirizzi IPv6.}
\label{fig:sock_sa_ipv6_struct}
\end{figure}
il campo \var{sin6\_flowinfo} è a sua volta diviso in tre parti di cui i 24
bit inferiori indicano l'etichetta di flusso, i successivi 4 bit la priorità e
gli ultimi 4 sono riservati. Questi valori fanno riferimento ad alcuni campi
-specifici dell'header dei pacchetti IPv6 (vedi \secref{sec:IP_ipv6head}) ed il
-loro uso è sperimentale.
-
-Il campo \var{sin6\_addr} contiene l'indirizzo a 128 bit usato da IPv6, infine
-il campo \var{sin6\_scope\_id} è un campo introdotto in Linux con il kernel
-2.4, per gestire alcune operazioni riguardanti il multicasting.
-
-Si noti che questa struttura ha una dimensione maggiore della struttura
-\struct{sockaddr} generica vista in \figref{fig:sock_sa_gen_struct}, quindi
+specifici dell'header dei pacchetti IPv6 (vedi sez.~\ref{sec:IP_ipv6head}) ed
+il loro uso è sperimentale.
+
+Il campo \var{sin6\_addr} contiene l'indirizzo a 128 bit usato da IPv6,
+espresso da un vettore di 16 byte. Infine il campo \var{sin6\_scope\_id} è un
+campo introdotto in Linux con il kernel 2.4, per gestire alcune operazioni
+riguardanti il \itindex{multicast} \textit{multicasting}. Si noti infine che
+\struct{sockaddr\_in6} ha una dimensione maggiore della struttura
+\struct{sockaddr} generica di fig.~\ref{fig:sock_sa_gen_struct}, quindi
occorre stare attenti a non avere fatto assunzioni riguardo alla possibilità
di contenere i dati nelle dimensioni di quest'ultima.
vengono chiamati \textit{local domain} o anche \textit{Unix domain}); essi
hanno la caratteristica ulteriore di poter essere creati anche in maniera
anonima attraverso la funzione \func{socketpair} (che abbiamo trattato in
-\secref{sec:ipc_socketpair}). Quando però si vuole fare riferimento esplicito
-ad uno di questi socket si deve usare una struttura degli indirizzi di tipo
-\struct{sockaddr\_un}, la cui definizione si è riportata in
-\secref{fig:sock_sa_local_struct}.
+sez.~\ref{sec:ipc_socketpair}). Quando però si vuole fare riferimento
+esplicito ad uno di questi socket si deve usare una struttura degli indirizzi
+di tipo \struct{sockaddr\_un}, la cui definizione si è riportata in
+fig.~\ref{fig:sock_sa_local_struct}.
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
\includestruct{listati/sockaddr_un.h}
\end{minipage}
- \caption{La struttura degli indirizzi dei socket locali (detti anche
- \textit{unix domain}) \structd{sockaddr\_un} definita in \file{sys/un.h}.}
+ \caption{La struttura \structd{sockaddr\_un} degli indirizzi dei socket
+ locali (detti anche \textit{unix domain}) definita in \file{sys/un.h}.}
\label{fig:sock_sa_local_struct}
\end{figure}
può essere un file (di tipo socket) nel filesystem o una stringa univoca
(mantenuta in uno spazio di nomi astratto). Nel primo caso l'indirizzo viene
specificato come una stringa (terminata da uno zero) corrispondente al
-pathname del file; nel secondo invece \var{sun\_path} inizia con uno zero e
-vengono usati come nome i restanti byte come stringa, senza terminazione.
+\itindex{pathname}\textit{pathname} del file; nel secondo invece
+\var{sun\_path} inizia con uno zero e vengono usati come nome i restanti byte
+come stringa, senza terminazione.
\subsection{La struttura degli indirizzi AppleTalk}
a pacchetto, di tipo \const{SOCK\_DGRAM}; l'argomento \param{protocol} di
\func{socket} deve essere nullo. È altresì possibile usare i socket raw
specificando un tipo \const{SOCK\_RAW}, nel qual caso l'unico valore valido
-per \param{protocol} è \func{ATPROTO\_DDP}.
+per \param{protocol} è \const{ATPROTO\_DDP}.
Gli indirizzi AppleTalk devono essere specificati tramite una struttura
\struct{sockaddr\_atalk}, la cui definizione è riportata in
-\figref{fig:sock_sa_atalk_struct}; la struttura viene dichiarata includendo il
-file \file{netatalk/at.h}.
+fig.~\ref{fig:sock_sa_atalk_struct}; la struttura viene dichiarata includendo
+il file \file{netatalk/at.h}.
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
\includestruct{listati/sockaddr_atalk.h}
\end{minipage}
- \caption{La struttura degli indirizzi dei socket AppleTalk
- \structd{sockaddr\_atalk}.}
+ \caption{La struttura \structd{sockaddr\_atalk} degli indirizzi dei socket
+ AppleTalk, e la struttura \structd{at\_addr} degli indirizzi AppleTalk.}
\label{fig:sock_sa_atalk_struct}
\end{figure}
Il campo \var{sat\_family} deve essere sempre \const{AF\_APPLETALK}, mentre il
campo \var{sat\_port} specifica la porta che identifica i vari servizi. Valori
inferiori a 129 sono usati per le \textsl{porte riservate}, e possono essere
-usati solo da processi con i privilegi di amministratore o con la capability
-\const{CAP\_NET\_BIND\_SERVICE}. L'indirizzo remoto è specificato nella
-struttura \var{sat\_addr}, e deve essere in \textit{network order} (vedi
-\secref{sec:sock_endianess}); esso è composto da un parte di rete data dal
-campo \var{s\_net}, che può assumere il valore \const{AT\_ANYNET}, che indica
-una rete generica e vale anche per indicare la rete su cui si è, il singolo
-nodo è indicato da \var{s\_node}, e può prendere il valore generico
-\const{AT\_ANYNODE} che indica anche il nodo corrente, ed il valore
-\const{ATADDR\_BCAST} che indica tutti i nodi della rete.
+usati solo da processi con i privilegi di amministratore o con la
+\itindex{capabilities}\textit{capability} \const{CAP\_NET\_BIND\_SERVICE}.
+L'indirizzo remoto è specificato nella struttura \var{sat\_addr}, e deve
+essere in \textit{network order} (vedi sez.~\ref{sec:sock_endianess}); esso è
+composto da un parte di rete data dal campo \var{s\_net}, che può assumere il
+valore \const{AT\_ANYNET}, che indica una rete generica e vale anche per
+indicare la rete su cui si è, il singolo nodo è indicato da \var{s\_node}, e
+può prendere il valore generico \const{AT\_ANYNODE} che indica anche il nodo
+corrente, ed il valore \const{ATADDR\_BCAST} che indica tutti i nodi della
+rete.
\subsection{La struttura degli indirizzi dei \textit{packet socket}}
I \textit{packet socket}, identificati dal dominio \const{PF\_PACKET}, sono
un'interfaccia specifica di Linux per inviare e ricevere pacchetti
-direttamente su un'interfaccia di rete, senza passare per le routine di
+direttamente su un'interfaccia di rete, senza passare per le funzioni di
gestione dei protocolli di livello superiore. In questo modo è possibile
implementare dei protocolli in user space, agendo direttamente sul livello
fisico. In genere comunque si preferisce usare la libreria \file{pcap}, che
pacchetti, qualunque sia il loro protocollo di collegamento. Ovviamente l'uso
di questi socket è una operazione privilegiata e può essere effettuati solo da
un processo con i privilegi di amministratore (user-ID effettivo nullo) o con
-la capability \const{CAP\_NET\_RAW}.
+la \itindex{capabilities}\textit{capability} \const{CAP\_NET\_RAW}.
Una volta aperto un \textit{packet socket}, tutti i pacchetti del protocollo
specificato passeranno attraverso di esso, qualunque sia l'interfaccia da cui
Nel caso dei \textit{packet socket} la struttura degli indirizzi è di tipo
\struct{sockaddr\_ll}, e la sua definizione è riportata in
-\figref{fig:sock_sa_packet_struct}; essa però viene ad assumere un ruolo
+fig.~\ref{fig:sock_sa_packet_struct}; essa però viene ad assumere un ruolo
leggermente diverso rispetto a quanto visto finora per gli altri tipi di
socket. Infatti se il socket è di tipo \const{SOCK\_RAW} si deve comunque
scrivere tutto direttamente nel pacchetto, quindi la struttura non serve più a
\file{linux/if\_arp.h}, mentre il campo \var{sll\_pkttype} indica il tipo di
pacchetto; entrambi vengono impostati alla ricezione di un pacchetto ed han
senso solo in questo caso. In particolare \var{sll\_pkttype} può assumere i
-seguenti valori: \var{PACKET\_HOST} per un pacchetto indirizzato alla macchina
-ricevente, \var{PACKET\_BROADCAST} per un pacchetto di broadcast,
-\var{PACKET\_MULTICAST} per un pacchetto inviato ad un indirizzo fisico di
-multicast, \var{PACKET\_OTHERHOST} per un pacchetto inviato ad un'altra
-stazione (e ricevuto su un'interfaccia in modo promiscuo),
-\var{PACKET\_OUTGOING} per un pacchetto originato dalla propria macchina che
+seguenti valori: \const{PACKET\_HOST} per un pacchetto indirizzato alla
+macchina ricevente, \const{PACKET\_BROADCAST} per un pacchetto di
+\itindex{broadcast} \textit{broadcast}, \const{PACKET\_MULTICAST} per un
+pacchetto inviato ad un indirizzo fisico di \itindex{multicast}
+\textit{multicast}, \const{PACKET\_OTHERHOST} per un pacchetto inviato ad
+un'altra stazione (e ricevuto su un'interfaccia in modo promiscuo),
+\const{PACKET\_OUTGOING} per un pacchetto originato dalla propria macchina che
torna indietro sul socket.
-Si tenga presente infine che in fase di ricezione, anche se si richiede il
-troncamento del pacchetto, le funzioni \func{recvmsg}, \func{recv} e
-\func{recvfrom} restituiranno comunque la lunghezza effettiva del pacchetto
-così come arrivato sulla linea.
+Si tenga presente infine che in fase di ricezione, anche se si richiede il
+troncamento del pacchetto, le funzioni \func{recv}, \func{recvfrom} e
+\func{recvmsg} (vedi sez.~\ref{sec:net_sendmsg}) restituiranno comunque la
+lunghezza effettiva del pacchetto così come arrivato sulla linea.
%% \subsection{La struttura degli indirizzi DECnet}
%% \label{sec:sock_sa_decnet}
% passaggio dipende dalla direzione del medesimo, dal processo al kernel o
% viceversa.
-% In particolare le tre funzioni \texttt{bind}, \texttt{connect} e
-% \texttt{sendto} passano la struttura al kernel, in questo caso è passata
+% In particolare le tre funzioni \func{bind}, \func{connect} e
+% \func{sendto} passano la struttura al kernel, in questo caso è passata
% \textsl{per valore} anche la dimensione della medesima
-% Le funzioni \texttt{accept}, \texttt{recvfrom}, \texttt{getsockname} e
-% \texttt{getpeername} invece ricevono i valori del kernel
+% Le funzioni \func{accept}, \func{recvfrom}, \func{getsockname} e
+% \func{getpeername} invece ricevono i valori del kernel
\label{sec:sock_addr_func}
In questa sezione tratteremo delle varie funzioni usate per manipolare gli
-indirizzi, limitandoci però agli indirizzi internet.
+indirizzi, limitandoci però agli indirizzi internet. Come accennato gli
+indirizzi e i numeri di porta usati nella rete devono essere forniti in
+formato opportuno (il \textit{network order}). Per capire cosa significa tutto
+ciò occorre introdurre un concetto generale che tornerà utile anche in
+seguito.
-Come accennato gli indirizzi e i numeri di porta usati nella rete devono
-essere forniti in formato opportuno (il \textit{network order}). Per capire
-cosa significa tutto ciò occorre introdurre un concetto generale che tornerà
-utile anche in seguito.
-
-\subsection{La \textit{endianess}\index{endianess}}
+\subsection{La \textit{endianess}}
\label{sec:sock_endianess}
+\itindbeg{endianess}
La rappresentazione di un numero binario in un computer può essere fatta in
due modi, chiamati rispettivamente \textit{big endian} e \textit{little
endian} a seconda di come i singoli bit vengono aggregati per formare le
variabili intere (ed in genere in diretta corrispondenza a come sono poi in
realtà cablati sui bus interni del computer).
+\begin{figure}[htb]
+ \centering
+ \includegraphics[height=3cm]{img/endianess}
+ \caption{Schema della disposizione dei dati in memoria a seconda della
+ \textit{endianess}.}
+ \label{fig:sock_endianess}
+\end{figure}
+
Per capire meglio il problema si consideri un intero a 32 bit scritto in una
locazione di memoria posta ad un certo indirizzo. Come illustrato in
-\figref{fig:sock_endianess} i singoli bit possono essere disposti un memoria
+fig.~\ref{fig:sock_endianess} i singoli bit possono essere disposti un memoria
in due modi: a partire dal più significativo o a partire dal meno
significativo. Così nel primo caso si troverà il byte che contiene i bit più
significativi all'indirizzo menzionato e il byte con i bit meno significativi
parte dal bit meno significativo è detto per lo stesso motivo \textit{little
endian}.
-\begin{figure}[htb]
- \centering
- \includegraphics[height=5cm]{img/endianess}
- \caption{Schema della disposizione dei dati in memoria a seconda della
- \textit{endianess}\index{endianess}.}
- \label{fig:sock_endianess}
-\end{figure}
-
-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 di uso di questi formati sono quello del bus PCI, che è
-\textit{little endian}, o quello del bus VME che è \textit{big endian}.
+Si può allora verificare quale tipo di \textit{endianess} usa il proprio
+computer con un programma elementare che si limita ad assegnare un valore ad
+una variabile per poi ristamparne il contenuto leggendolo un byte alla volta.
+Il codice di detto programma, \file{endtest.c}, è nei sorgenti allegati,
+allora se lo eseguiamo su un PC otterremo:
+\begin{verbatim}
+[piccardi@gont sources]$ ./endtest
+Using value ABCDEF01
+val[0]= 1
+val[1]=EF
+val[2]=CD
+val[3]=AB
+\end{verbatim}%$
+mentre su di un Mac avremo:
+\begin{verbatim}
+piccardi@anarres:~/gapil/sources$ ./endtest
+Using value ABCDEF01
+val[0]=AB
+val[1]=CD
+val[2]=EF
+val[3]= 1
+\end{verbatim}%$
+
+
+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 dei dati contenuti nelle intestazioni dei protocolli di rete è
+anch'esso \textit{big endian}; altri esempi di uso di questi due diversi
+formati 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
resta sempre lo stesso, anche quando il processore permetterebbe di eseguire
questi cambiamenti.
+\begin{figure}[htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/endian.c}
+ \end{minipage}
+ \normalsize
+ \caption{La funzione \func{endian}, usata per controllare il tipo di
+ architettura della macchina.}
+ \label{fig:sock_endian_code}
+\end{figure}
+
+Per controllare quale tipo di ordinamento si ha sul proprio computer si è
+scritta una piccola funzione di controllo, il cui codice è riportato
+fig.~\ref{fig:sock_endian_code}, che restituisce un valore nullo (falso) se
+l'architettura è \textit{big endian} ed uno non nullo (vero) se l'architettura
+è \textit{little endian}.
+
+Come si vede la funzione è molto semplice, e si limita, una volta assegnato
+(\texttt{\small 9}) un valore di test pari a \texttt{0xABCD} ad una variabile
+di tipo \ctyp{short} (cioè a 16 bit), a ricostruirne una copia byte a byte.
+Per questo prima (\texttt{\small 10}) si definisce il puntatore \var{ptr} per
+accedere al contenuto della prima variabile, ed infine calcola (\texttt{\small
+ 11}) il valore della seconda assumendo che il primo byte sia quello meno
+significativo (cioè, per quanto visto in fig.~\ref{fig:sock_endianess}, che sia
+\textit{little endian}). Infine la funzione restituisce (\texttt{\small 12})
+il valore del confonto delle due variabili.
+\itindend{endianess}
+
+
+
\subsection{Le funzioni per il riordinamento}
\label{sec:sock_func_ord}
-Il problema connesso all'endianess\index{endianess} è che quando si passano
+Il problema connesso all'endianess\itindex{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 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:
+con i due byte in cui è suddiviso scambiati di posto. 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{ntohl} e \funcd{ntohs} ed i rispettivi prototipi sono:
\begin{functions}
\headdecl{netinet/in.h}
\funcdecl{unsigned long int htonl(unsigned long int hostlong)}
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)}
+ \funcdecl{unsigned long int ntohl(unsigned long int netlong)}
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)}
+ \funcdecl{unsigned sort int ntohs(unsigned short int netshort)}
Converte l'intero a 16 bit \param{netshort} dal formato della rete a quello
della macchina.
La funzione \func{inet\_aton} converte la stringa puntata da \param{src}
nell'indirizzo binario che viene memorizzato nell'opportuna struttura
-\struct{in\_addr} (si veda \secref{fig:sock_sa_ipv4_struct}) situata
+\struct{in\_addr} (si veda fig.~\ref{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 restituisce 0 in caso di successo e 1
ricordare il tipo di conversione effettuata e stanno per \textit{presentation}
e \textit{numeric}.
-% \begin{figure}[htb]
-% \centering
-
-% \caption{Schema della rappresentazioni utilizzate dalle funzioni di
-% conversione \texttt{inet\_pton} e \texttt{inet\_ntop} }
-% \label{fig:sock_inet_conv_func}
-
-% \end{figure}
-
Entrambe le funzioni accettano l'argomento \param{af} che indica il tipo di
indirizzo, e che può essere soltanto \const{AF\_INET} o \const{AF\_INET6}. La
prima funzione, \funcd{inet\_pton}, serve a convertire una stringa in un
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.
+sez.~\ref{sec:IP_ipv6_notation} per IPv6.
\index{socket|)}