Program Interface}) usata nella programmazione di rete. La loro origine
risale al 1983, quando furono introdotti nel BSD 4.2; l'interfaccia è rimasta
sostanzialmente la stessa con piccole modifiche negli anni successivi. Benché
-siano state sviluppate interfacce alternative, originate dai sistemi SYSV,
+siano state sviluppate interfacce alternative, originate dai sistemi SVr4,
come la XTI (\textit{X/Open Transport Interface}) nessuna ha mai raggiunto la
diffusione e la popolarità di quella dei socket (né tantomeno usabilità e
flessibilità).
La scelta di uno stile dipende sia dai meccanismi disponibili, sia dal tipo di
comunicazione che si vuole effettuare. Ad esempio alcuni stili di
-comunicazione considerano i dati come una sequenza continua di bytes, altri
+comunicazione considerano i dati come una sequenza continua di byte, altri
invece li raggruppano in blocchi (i pacchetti).
Un'altro esempio di stile concerne la possibilità che la comunicazione possa o
socket, per cui viene messo a zero (con l'eccezione dei \textit{raw socket}).
\begin{prototype}{sys/socket.h}{int socket(int domain, int type, int protocol)}
+
+ Apre un socket.
- La funzione restituisce un intero positivo se riesce, e -1 se fallisce, in
- quest'ultimo caso la variabile \var{errno} è settata con i seguenti
- codici di errore:
+ \bodydesc{La funzione restituisce un intero positivo se riesce, e -1 se
+ fallisce, in quest'ultimo caso la variabile \var{errno} è settata con i
+ seguenti codici di errore:
\begin{errlist}
- \item \macro{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 \macro{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 \macro{EMFILE} Si è ecceduta la tabella dei file.
- \item \macro{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 \macro{EINVAL} Protocollo sconosciuto o dominio non disponibile.
- \item \macro{ENOBUFS} o \macro{ENOMEM} Non c'è sufficiente memoria per
- creare il socket.
- \end{errlist}
+ \item[\macro{EINVAL}] Protocollo sconosciuto o dominio non disponibile.
+ \item[\macro{ENOBUFS}] Non c'è sufficiente memoria per creare il socket (può
+ essere anche \macro{ENOMEM}).
+ \end{errlist}}
\end{prototype}
Si noti che la creazione del socket non comporta nulla riguardo
\begin{table}[htb]
\footnotesize
\centering
- \begin{tabular}[c]{lll}
+ \begin{tabular}[c]{|l|l|l|}
\hline
- \textsl{Nome} & \textsl{Utilizzo} &\textsl{Man page} \\
+ \textbf{Nome} & \textbf{Utilizzo} &\textbf{Man page} \\
\hline
\hline
- PF\_UNIX,PF\_LOCAL & Local communication & unix(7) \\
- PF\_INET & IPv4 Internet protocols & ip(7) \\
- PF\_INET6 & IPv6 Internet protocols & \\
- PF\_IPX & IPX - Novell protocols & \\
- PF\_NETLINK & Kernel user interface device & netlink(7) \\
- PF\_X25 & ITU-T X.25 / ISO-8208 protocol & x25(7) \\
- PF\_AX25 & Amateur radio AX.25 protocol & \\
- PF\_ATMPVC & Access to raw ATM PVCs & \\
- PF\_APPLETALK & Appletalk & ddp(7) \\
- PF\_PACKET & Low level packet interface & packet(7) \\
+ \macro{PF\_UNIX},
+ \macro{PF\_LOCAL} & Local communication & unix(7) \\
+ \macro{PF\_INET} & IPv4 Internet protocols & ip(7) \\
+ \macro{PF\_INET6} & IPv6 Internet protocols & \\
+ \macro{PF\_IPX} & IPX - Novell protocols & \\
+ \macro{PF\_NETLINK}& Kernel user interface device & netlink(7) \\
+ \macro{PF\_X25} & ITU-T X.25 / ISO-8208 protocol & x25(7) \\
+ \macro{PF\_AX25} & Amateur radio AX.25 protocol & \\
+ \macro{PF\_ATMPVC} & Access to raw ATM PVCs & \\
+ \macro{PF\_APPLETALK}& Appletalk & ddp(7) \\
+ \macro{PF\_PACKET} & Low level packet interface & packet(7) \\
\hline
\end{tabular}
\caption{Famiglie di protocolli definiti in Linux}
maneggiare puntatori a strutture relative a tutti gli indirizzi possibili
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 \type{void *}), ma l'interfaccia dei socket è antecendente alla
+(i \type{void *}), ma l'interfaccia dei socket è antecedente alla
definizione dello standard ANSI, e per questo nel 1982 fu scelto di definire
una struttura generica \type{sockaddr} per gli indirizzi dei socket mostrata
in \nfig:
\centering
\begin{tabular}{|l|l|l|}
\hline
- \multicolumn{1}{|c|}{Tipo}& \multicolumn{1}{|c|}{Descrizione}&
- \multicolumn{1}{|c|}{Header} \\
+ \multicolumn{1}{|c|}{\textbf{Tipo}}&
+ \multicolumn{1}{|c|}{\textbf{Descrizione}}&
+ \multicolumn{1}{|c|}{\textbf{Header}} \\
\hline
\hline
- \texttt{int8\_t} & intero a 8 bit con segno & \texttt{sys/types.h}\\
- \texttt{uint8\_t} & intero a 8 bit senza segno & \texttt{sys/types.h}\\
- \texttt{int16\_t} & intero a 16 bit con segno & \texttt{sys/types.h}\\
- \texttt{uint16\_t} & intero a 16 bit senza segno& \texttt{sys/types.h}\\
- \texttt{int32\_t} & intero a 32 bit con segno & \texttt{sys/types.h}\\
- \texttt{uint32\_t} & intero a 32 bit senza segno& \texttt{sys/types.h}\\
+ \type{int8\_t} & intero a 8 bit con segno & \file{sys/types.h}\\
+ \type{uint8\_t} & intero a 8 bit senza segno & \file{sys/types.h}\\
+ \type{int16\_t} & intero a 16 bit con segno & \file{sys/types.h}\\
+ \type{uint16\_t} & intero a 16 bit senza segno& \file{sys/types.h}\\
+ \type{int32\_t} & intero a 32 bit con segno & \file{sys/types.h}\\
+ \type{uint32\_t} & intero a 32 bit senza segno& \file{sys/types.h}\\
\hline
- \texttt{sa\_family\_t} & famiglia degli indirizzi& \texttt{sys/socket.h}\\
- \texttt{socklen\_t} & lunghezza (\texttt{uint32\_t}) dell'indirizzo di
- un socket& \texttt{sys/socket.h}\\
+ \type{sa\_family\_t} & famiglia degli indirizzi& \file{sys/socket.h}\\
+ \type{socklen\_t} & lunghezza (\type{uint32\_t}) dell'indirizzo di
+ un socket& \type{sys/socket.h}\\
\hline
- \texttt{in\_addr\_t} & indirizzo IPv4 (\texttt{uint32\_t}) &
- \texttt{netinet/in.h}\\
- \texttt{in\_port\_t} & porta TCP o UDP (\texttt{uint16\_t})&
- \texttt{netinet/in.h}\\
+ \type{in\_addr\_t} & indirizzo IPv4 (\file{uint32\_t}) &
+ \type{netinet/in.h}\\
+ \type{in\_port\_t} & porta TCP o UDP (\file{uint16\_t})&
+ \type{netinet/in.h}\\
\hline
\end{tabular}
\caption{Tipi di dati usati nelle strutture degli indirizzi, secondo quanto
(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 \var{sun\_path} inizia con uno zero
-vengono usati i restanti bytes come stringa (senza terminazione).
+vengono usati i restanti byte come stringa (senza terminazione).
% \subsection{Il passaggio delle strutture}
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 bytes in cui è
+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.
Converte l'intero a 16 bit \var{netshort} dal formato della rete a quello
della macchina.
\end{prototype}
-I nomi sono assegnati usando la lettera \func{n} come mnemonico per indicare
+I nomi sono assegnati usando la lettera \texttt{n} come mnemonico per indicare
l'ordinamento usato sulla rete (da \textit{network order}) e la lettera
-\func{h} come mnemonico per l'ordinamento usato sulla macchina locale (da
-\textit{host order}), mentre le lettere \func{s} e \func{l} stanno ad indicare
-i tipi di dato (\type{long} o \type{short}, riportati anche dai prototipi).
+\texttt{h} come mnemonico per l'ordinamento usato sulla macchina locale (da
+\textit{host order}), mentre le lettere \texttt{s} e \texttt{l} stanno ad
+indicare i tipi di dato (\type{long} o \type{short}, riportati anche dai
+prototipi).
Usando queste funzioni si ha la conversione automatica: nel caso in cui la
macchina che si sta usando abbia una architettura \textit{big endian} queste
indirizzi IPv4 da una stringa in cui il numero di IP è espresso secondo la
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 \func{a} come
+ 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)}
Le tre funzioni precedenti sono limitate solo ad indirizzi IPv4, per questo
motivo è preferibile usare le due nuove funzioni \func{inet\_pton} e
\func{inet\_ntop} che possono convertire anche gli indirizzi IPv6. Anche in
-questo caso le lettere \func{n} e \func{p} sono degli mnemonici per ricordare
-il tipo di conversione effettuata e stanno per \textit{presentation} e
-\textit{numeric}.
+questo caso le lettere \texttt{n} e \texttt{p} sono degli mnemonici per
+ricordare il tipo di conversione effettuata e stanno per \textit{presentation}
+e \textit{numeric}.
% \begin{figure}[htb]
% \centering
% \end{figure}
-Entrambe le funzioni accettano l'argomento \texttt{af} che indica il tipo di
-indirizzo e può essere \texttt{AF\_INET} o \texttt{AF\_INET6}. Se la famiglia
-indicata non è valida entrambe le funzioni settano la variabile \texttt{errno}
-al valore \texttt{EAFNOSUPPORT}. I prototipi delle suddette funzioni sono i
+Entrambe le funzioni accettano l'argomento \param{af} che indica il tipo di
+indirizzo e può essere \macro{AF\_INET} o \macro{AF\_INET6}. Se la famiglia
+indicata non è valida entrambe le funzioni settano la variabile \var{errno}
+al valore \macro{EAFNOSUPPORT}. I prototipi delle suddette funzioni sono i
seguenti:
\begin{prototype}{sys/socket.h}
{int inet\_pton(int af, const char *src, void *addr\_ptr)} Converte la
\macro{INET6\_ADDRSTRLEN} per indirizzi IPv6; la lunghezza del buffer deve
comunque venire specificata attraverso il parametro \var{len}.
- 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 \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.
+ \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 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.}
\end{prototype}
-Gli indirizzi vengono cnovertiti da/alle rispettive strutture di indirizzo
+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
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, esamimeremo una caratteristica
+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.
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 bytes minore di
+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.
In questo caso tutto quello che il programma chiamante deve fare è di ripetere
-la lettura (o scrittura) per la quantità di bytes rimanenti (lo stesso può
-avvenire scrivendo più di 4096 bytes in una pipe, dato che quello è il limite
+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).
\begin{figure}[htb]
return (count - nleft);
}
\end{lstlisting}
- \caption{Funzione \func{SockRead}, legge \var{count} bytes da un socket }
+ \caption{Funzione \func{SockRead}, legge \var{count} byte da un socket }
\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 bytes specificato; il sorgente
+avere letto o scritto esattamente il numero di byte specificato; il sorgente
è riportato in \curfig\ e \nfig\ ed è disponibile fra i sorgenti allegati alla
guida nei files \file{SockRead.c} e \file{SockWrite.c}.
return (count);
}
\end{lstlisting}
- \caption{Funzione \func{SockWrite}, scrive \var{count} bytes su un socket }
+ \caption{Funzione \func{SockWrite}, scrive \var{count} byte su un socket }
\label{fig:sock_SockWrite_code}
\end{figure}
Come si può notare le funzioni ripetono la lettura/scrittura in un ciclo fino
-all'esaurimento del numero di bytes richiesti, in caso di errore viene
+all'esaurimento del numero di byte richiesti, in caso di errore viene
controllato se questo è \macro{EINTR} (cioè un'interruzione della system call
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 bytes letti è zero, significa che si è
+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 bytes richiesti.
+lettura di tutti i byte richiesti.
\begin{lstlisting}{}
#include <sys/types.h> /* predefined types */
#include <unistd.h> /* include unix standard library */
-#include <arpa/inet.h> /* IP addresses conversion utiliites */
+#include <arpa/inet.h> /* IP addresses conversion utilities */
#include <sys/socket.h> /* socket library */
#include <stdio.h> /* include standard I/O library */
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 routines illustrate in
+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
\begin{lstlisting}{}
#include <sys/types.h> /* predefined types */
#include <unistd.h> /* include unix standard library */
-#include <arpa/inet.h> /* IP addresses conversion utiliites */
+#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>
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.
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End: