in questa sezione vedremo come è possibile creare un socket e come specificare
il tipo di comunicazione che esso deve utilizzare.
-\subsection{La funzione \texttt{socket}}
+\subsection{La funzione \func{socket}}
\label{sec:sock_socket}
La creazione di un socket avviene attraverso l'uso della funzione
-\texttt{socket} questa restituisce un \textit{socket descriptor} (un valore
+\func{socket} questa restituisce un \textit{socket descriptor} (un valore
intero non negativo) che come gli analoghi file descriptor di file e alle
pipe serve come riferimento al socket; in sostanza è l'indice nella tabella
dei file che contiene i puntatori alle opportune strutture usate dal kernel ed
\begin{prototype}{sys/socket.h}{int socket(int domain, int type, int protocol)}
La funzione restituisce un intero positivo se riesce, e -1 se fallisce, in
- quest'ultimo caso la variabile \texttt{errno} è settata con i seguenti
+ quest'ultimo caso la variabile \var{errno} è settata con i seguenti
codici di errore:
\begin{errlist}
- \item \texttt{EPROTONOSUPPORT} Il tipo di socket o il protocollo scelto non
+ \item \macro{EPROTONOSUPPORT} Il tipo di socket o il protocollo scelto non
sono supportati nel dominio.
- \item \texttt{ENFILE} Il kernel non ha memoria sufficiente a creare una
+ \item \macro{ENFILE} Il kernel non ha memoria sufficiente a creare una
nuova struttura per il socket.
- \item \texttt{EMFILE} Si è ecceduta la tabella dei file.
- \item \texttt{EACCES} Non si hanno privilegi per creare un socket nel
+ \item \macro{EMFILE} Si è ecceduta la tabella dei file.
+ \item \macro{EACCES} Non si hanno privilegi per creare un socket nel
dominio o con il protocollo specificato.
- \item \texttt{EINVAL} Protocollo sconosciuto o dominio non disponibile.
- \item \texttt{ENOBUFS} o \texttt{ENOMEM} Non c'è sufficiente memoria per
+ \item \macro{EINVAL} Protocollo sconosciuto o dominio non disponibile.
+ \item \macro{ENOBUFS} o \macro{ENOMEM} Non c'è sufficiente memoria per
creare il socket.
\end{errlist}
\end{prototype}
Ogni famiglia di protocolli ha ovviamente una sua forma di indirizzamento e in
corrispondenza a questa una sua peculiare struttura degli indirizzi; i nomi di
-tutte queste strutture iniziano per \texttt{sockaddr\_}, quelli propri di
+tutte queste strutture iniziano per \var{sockaddr\_}, quelli propri di
ciascuna famiglia vengono identificati dal suffisso finale, aggiunto al nome
precedente.
\end{table}
In alcuni sistemi la struttura è leggermente diversa e prevede un primo membro
-aggiuntivo \texttt{uint8\_t sin\_len} (come riportato da R. Stevens nei suoi
+aggiuntivo \var{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 \type{unsigned short}.
Dal punto di vista del programmatore l'unico uso di questa struttura è quello
di fare da riferimento per il casting, per il kernel le cose sono un po'
diverse, in quanto esso usa il puntatore per recuperare il campo
-\texttt{sa\_family} con cui determinare il tipo di indirizzo; per questo
-motivo, anche se l'uso di un puntatore \texttt{void *} sarebbe più immediato
+\var{sa\_family} con cui determinare il tipo di indirizzo; per questo
+motivo, anche se l'uso di un puntatore \type{void *} sarebbe più immediato
per l'utente (che non dovrebbe più eseguire il casting), è stato mantenuto
l'uso di questa struttura.
I socket di tipo \macro{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
-\texttt{netinet/in.h} e secondo le man page ha la forma mostrata in \nfig,
+\file{netinet/in.h} e secondo le man page ha la forma mostrata in \nfig,
conforme allo standard POSIX.1g.
\begin{figure}[!htb]
};
\end{lstlisting}
\caption{La struttura degli indirizzi dei socket internet (IPv4)
- \texttt{sockaddr\_in}.}
+ \type{sockaddr\_in}.}
\label{fig:sock_sa_ipv4_struct}
\end{figure}
RAW che accedono direttamente al livello di IP, nel qual caso il numero della
porta viene settato al numero di protocollo.
-Il membro \texttt{sin\_family} deve essere sempre settato; \texttt{sin\_port}
+Il membro \var{sin\_family} deve essere sempre settato; \var{sin\_port}
specifica il numero di porta (vedi \secref{sec:TCPel_port_num}; i numeri di
porta sotto il 1024 sono chiamati \textsl{riservati} in quanto utilizzati da
servizi standard. Soltanto processi con i privilegi di root (effective uid
-uguale a zero) o con la capability \texttt{CAP\_NET\_BIND\_SERVICE} possono
+uguale a zero) o con la capability \macro{CAP\_NET\_BIND\_SERVICE} possono
usare la funzione \func{bind} su queste porte.
-Il membro \texttt{sin\_addr} contiene l'indirizzo internet dell'altro capo
+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
accedere alle diverse classi di indirizzi) che come intero.
\subsection{La struttura degli indirizzi IPv6}
\label{sec:sock_sa_ipv6}
-Essendo IPv6 una estensione di IPv4 i socket di tipo \texttt{PF\_INET6} sono
+Essendo IPv6 una estensione di IPv4 i socket di tipo \macro{PF\_INET6} sono
sostanzialmente identici ai precedenti; la parte in cui si trovano
praticamente tutte le differenze è quella della struttura degli indirizzi. La
-struttura degli indirizzi è definita ancora in \texttt{netinet/in.h}.
+struttura degli indirizzi è definita ancora in \file{netinet/in.h}.
\begin{figure}[!htb]
\footnotesize
};
\end{lstlisting}
\caption{La struttura degli indirizzi dei socket IPv6
- \texttt{sockaddr\_in6}.}
+ \type{sockaddr\_in6}.}
\label{fig:sock_sa_ipv6_struct}
\end{figure}
-Il campo \texttt{sin6\_family} deve essere sempre settato ad
-\texttt{AF\_INET6}, il campo \texttt{sin6\_port} è analogo a quello di IPv4 e
-segue le stesse regole; il campo \texttt{sin6\_flowinfo} è a sua volta diviso
+Il campo \var{sin6\_family} deve essere sempre settato ad
+\macro{AF\_INET6}, il campo \var{sin6\_port} è analogo a quello di IPv4 e
+segue le stesse regole; 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 \texttt{sin6\_addr} contiene l'indirizzo a 128 bit usato da IPv6,
-infine il campo \texttt{sin6\_scope\_id} è un campo introdotto con il kernel
+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 \texttt{sockaddr} generica,
+Si noti che questa struttura è più grande di una \var{sockaddr} generica,
quindi occorre stare attenti a non avere fatto assunzioni riguardo alla
possibilità di contenere i dati nelle dimensioni di quest'ultima.
\subsection{La struttura degli indirizzi locali}
\label{sec:sock_sa_local}
-I socket di tipo \texttt{PF\_UNIX} vengono usati per una comunicazione
+I socket di tipo \macro{PF\_UNIX} vengono usati per una comunicazione
efficiente fra processi che stanno sulla stessa macchina; essi rispetto ai
precedenti possono essere anche creati in maniera anonima attraverso la
-funzione \texttt{socketpair}. Quando però si vuole fare riferimento esplicito
+funzione \func{socketpair}. Quando però si vuole fare riferimento esplicito
ad uno di questi socket si deve usare la seguente struttura di indirizzi
-definita nel file di header \texttt{sys/un.h}.
+definita nel file di header \file{sys/un.h}.
\begin{figure}[!htb]
\footnotesize
};
\end{lstlisting}
\caption{La struttura degli indirizzi dei socket locali
- \texttt{sockaddr\_un}.}
+ \var{sockaddr\_un}.}
\label{fig:sock_sa_local_struct}
\end{figure}
-In questo caso il campo \texttt{sun\_family} deve essere \texttt{AF\_UNIX},
-mentre il campo \texttt{sun\_path} deve specificare un indirizzo; questo ha
+In questo caso il campo \var{sun\_family} deve essere \macro{AF\_UNIX},
+mentre il campo \var{sun\_path} deve specificare un indirizzo; questo ha
due forme un file (di tipo socket) nel filesystem o una stringa univoca
(tenuta 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 \texttt{sun\_path} inizia con uno zero
+pathname del file; nel secondo invece \var{sun\_path} inizia con uno zero
vengono usati i restanti bytes come stringa (senza terminazione).
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 settata la variabile \texttt{errno} con il valore \macro{ENOSPC} in
+ viene settata la variabile \var{errno} con il valore \macro{ENOSPC} in
caso le dimensioni dell'indirizzo eccedano la lunghezza specificata da
\var{len} o \macro{ENOAFSUPPORT} in caso \var{af} non sia una famiglia di
indirizzi valida.
\label{fig:net_cli_code}
\end{figure}
-Il sorgente completo del programma (\texttt{ElemDaytimeTCPClient.c}, che
+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.
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
-\texttt{inet\_pton} per convertire l'indirizzo numerico passato dalla linea di
+\func{inet\_pton} per convertire l'indirizzo numerico passato dalla linea di
comando.
Usando la funzione \func{connect} sul socket creato in precedenza
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 \texttt{stdout}.
+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
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
-(\texttt{ElemDaytimeTCPServer.c}) è allegato insieme agli altri file nella
-directory \texttt{sources}.
+(\file{ElemDaytimeTCPServer.c}) è allegato insieme agli altri file nella
+directory \file{sources}.
\begin{figure}[!htbp]
\footnotesize