%% othersock.tex
%%
-%% Copyright (C) 2004 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2004-2007 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".
%%
+
\chapter{Gli altri tipi di socket}
\label{cha:other_socket}
-Dopo aver trattato in cap.~\ref{cha:TCP_socket} i socket TCP, che costituiscono
-l'esempio più comune dell'interfaccia dei socket, esamineremo in questo
-capitolo gli altri tipi di socket, a partire dai socket UDP, e i socket
-\textit{Unix domain} già incontrati in \secref{sec:ipc_socketpair}.
+Dopo aver trattato in cap.~\ref{cha:TCP_socket} i socket TCP, che
+costituiscono l'esempio più comune dell'interfaccia dei socket, esamineremo in
+questo capitolo gli altri tipi di socket, a partire dai socket UDP, e i socket
+\textit{Unix domain} già incontrati in sez.~\ref{sec:ipc_socketpair}.
\section{I socket UDP}
Questa differenza comporta ovviamente che anche le modalità con cui si usano i
socket UDP sono completamente diverse rispetto ai socket TCP, ed in
particolare non esistendo il concetto di connessione non esiste il meccanismo
-del \textit{three way handshake} né quello degli stati del protocollo. In
-realtà tutto quello che avviene nella comunicazione attraverso dei socket UDP
-è la trasmissione di un pacchetto da un client ad un server o viceversa,
-secondo lo schema illustrato in fig.~\ref{fig:UDP_packet-exchange}.
+del \itindex{three~way~handshake} \textit{three way handshake} né quello degli
+stati del protocollo. In realtà tutto quello che avviene nella comunicazione
+attraverso dei socket UDP è la trasmissione di un pacchetto da un client ad un
+server o viceversa, secondo lo schema illustrato in
+fig.~\ref{fig:UDP_packet-exchange}.
\begin{figure}[htb]
\centering
prima di queste funzioni è \funcd{sendto} ed il suo prototipo\footnote{il
prototipo illustrato è quello utilizzato dalle \acr{glibc}, che seguono le
\textit{Single Unix Specification}, l'argomento \param{flags} era di tipo
- \type{int} nei vari BSD4.*, mentre nelle \acr{libc4} e \acr{libc5} veniva
- usato un \type{unsigned int}; l'argomento \param{len} era \type{int} nei
+ \texttt{int} nei vari BSD4.*, mentre nelle \acr{libc4} e \acr{libc5} veniva
+ usato un \texttt{unsigned int}; l'argomento \param{len} era \texttt{int} nei
vari BSD4.* e nelle \acr{libc4}, ma \type{size\_t} nelle \acr{libc5}; infine
- l'argomento \param{tolen} era \type{int} nei vari BSD4.* nelle \acr{libc4} e
- nelle \acr{libc5}.} è:
+ l'argomento \param{tolen} era \texttt{int} nei vari BSD4.* nelle \acr{libc4}
+ e nelle \acr{libc5}.} è:
\begin{functions}
\headdecl{sys/types.h}
\headdecl{sys/socket.h}
funzionamento della comunicazione attraverso il socket (come
\const{MSG\_NOSIGNAL} che impedisce l'invio del segnale \const{SIGPIPE} quando
si è già chiuso il capo locale della connessione). Torneremo con maggiori
-dettagli sul significato di questo argomento in sez.~\ref{sec:xxx_sendmsg},
+dettagli sul significato di questo argomento in sez.~\ref{sec:net_sendmsg},
dove tratteremo le funzioni avanzate dei socket, per il momento ci si può
limitare ad usare sempre un valore nullo.
\funcd{recvfrom}, che serve a ricevere i dati inviati da un altro socket; il
suo prototipo\footnote{il prototipo è quello delle \acr{glibc} che seguono le
\textit{Single Unix Specification}, i vari BSD4.*, le \acr{libc4} e le
- \acr{libc5} usano un \type{int} come valore di ritorno; per gli argomenti
+ \acr{libc5} usano un \texttt{int} come valore di ritorno; per gli argomenti
\param{flags} e \param{len} vale quanto detto a proposito di \func{sendto};
- infine l'argomento \param{fromlen} è \type{int} per i vari BSD4.*, le
+ infine l'argomento \param{fromlen} è \texttt{int} per i vari BSD4.*, le
\acr{libc4} e le \acr{libc5}.} è:
\begin{functions}
\headdecl{sys/types.h}
l'indirizzo del mittente del pacchetto che è stato ricevuto, e devono essere
opportunamente inizializzati con i puntatori alle variabili dove la struttura
contenente quest'ultimo e la relativa lunghezza saranno scritti (si noti che
-\param{fromlen} è un valore intero ottenuto come \textit{value return
- argument}). Se non si è interessati a questa informazione, entrambi gli
-argomenti devono essere inizializzati al valore \const{NULL}.
+\param{fromlen} è un valore intero ottenuto come
+\itindex{value~result~argument} \textit{value result argument}). Se non si è
+interessati a questa informazione, entrambi gli argomenti devono essere
+inizializzati al valore \const{NULL}.
Una differenza fondamentale del comportamento di queste funzioni rispetto alle
usuali \func{read} e \func{write} che abbiamo usato con i socket TCP è che in
struttura degli indirizzi; prima (\texttt{\small 14}) si cancella
completamente la stessa con \func{memset}, (\texttt{\small 15}) poi si imposta
la famiglia dell'indirizzo ed infine (\texttt{\small 16} la porta. Infine
-(\texttt{\small 18--21}) si ricava l'indirizzo del server da contattare dal
-parametro passato a riga di comando, convertendolo con \func{inet\_pton}. Si
-noti come questa sezione sia identica a quella del client TCP di
+(\texttt{\small 18--21}) si ricava l'indirizzo del server da contattare
+dall'argomento passato a riga di comando, convertendolo con \func{inet\_pton}.
+Si noti come questa sezione sia identica a quella del client TCP di
fig.~\ref{fig:TCP_daytime_client_code}, in quanto la determinazione dell'uso
di UDP al posto di TCP è stata effettuata quando si è creato il socket.
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15.6cm}
- \includecodesample{listati/UDP_ClientEcho.c}
+ \includecodesample{listati/UDP_ClientEcho_first.c}
\end{minipage}
\normalsize
\caption{Codice della funzione \func{ClientEcho} usata dal client per il
Quando si chiama \func{connect} su di un socket UDP tutto quello che succede è
che l'indirizzo passato alla funzione viene registrato come indirizzo di
-destinazione del socket, a differenza di quanto avviene con TCP non viene
-scambiato nessun pacchetto; tutto quello che succede è che da quel momento in
+destinazione del socket. A differenza di quanto avviene con TCP non viene
+scambiato nessun pacchetto, tutto quello che succede è che da quel momento in
qualunque cosa si scriva sul socket sarà inviata a quell'indirizzo; non sarà
più necessario usare l'argomento \param{to} di \func{sendto} per specificare
la destinazione dei pacchetti, che potranno essere inviati e ricevuti usando
l'argomento \param{to} deve essere inizializzato a \const{NULL}, e
\param{tolen} deve essere inizializzato a zero, pena un errore.}
-Una volta che il socket è connesso però cambia anche il comportamento in
+Una volta che il socket è connesso cambia però anche il comportamento in
ricezione; prima infatti il kernel avrebbe restituito al socket qualunque
pacchetto ricevuto con un indirizzo di destinazione corrispondente a quello
del socket, senza nessun controllo sulla sorgente; una volta che il socket
viene connesso saranno riportati su di esso solo i pacchetti con un indirizzo
-sorgente corrispondente a quello a cui ci si è connessi.
+sorgente corrispondente a quello a cui ci si è connessi.
-Infine quando si è connesso un socket, venendo meno l'ambiguità segnalata alla
-fine di sez.~\ref{sec:UDP_problems}, tutti gli eventuali errori asincroni
-vengono riportati alle funzioni che operano su di esse, pertanto con le
-modifiche illustrate in fig.~\ref{fig:UDP_echo_conn_cli}.
+Infine quando si usa un socket connesso, venendo meno l'ambiguità segnalata
+alla fine di sez.~\ref{sec:UDP_problems}, tutti gli eventuali errori asincroni
+vengono riportati alle funzioni che operano su di esso; pertanto potremo
+riscrivere il nostro client per il servizio \textit{echo} con le modifiche
+illustrate in fig.~\ref{fig:UDP_echo_conn_cli}.
\begin{figure}[!htb]
\footnotesize \centering
\includecodesample{listati/UDP_echo.c}
\end{minipage}
\normalsize
- \caption{Nuova sezione della seconda versione del client del servizio
- \textit{echo} che utilizza socket UDP connessi.}
+ \caption{Seconda versione del client del servizio \textit{echo} che utilizza
+ socket UDP connessi.}
\label{fig:UDP_echo_conn_cli}
\end{figure}
+Ed in questo caso rispetto alla precedente versione, il solo cambiamento è
+l'utilizzo (\texttt{\small 17}) della funzione \func{connect} prima della
+chiamata alla funzione di gestione del protocollo, che a sua volta è stata
+modificata eliminando l'indirizzo passato come argomento e sostituendo le
+chiamata a \func{sendto} e \func{recvfrom} con chiamate a \func{read} e
+\func{write} come illustrato dal nuovo codice riportato in
+fig.~\ref{fig:UDP_echo_conn_echo_client}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/UDP_ClientEcho.c}
+ \end{minipage}
+ \normalsize
+ \caption{Seconda versione della funzione \func{ClientEcho}.}
+ \label{fig:UDP_echo_conn_echo_client}
+\end{figure}
+
+Utilizzando questa nuova versione del client si può verificare che quando ci
+si rivolge verso un indirizzo inesistente o su cui non è in ascolto un server
+si è in grado rilevare l'errore, se infatti eseguiamo il nuovo programma
+otterremo un qualcosa del tipo:
+\begin{verbatim}
+[piccardi@gont sources]$ ./echo 192.168.1.1
+prova
+Errore in lettura: Connection refused
+\end{verbatim}%$
+
+Ma si noti che a differenza di quanto avveniva con il client TCP qui l'errore
+viene rilevato soltanto dopo che si è tentato di inviare qualcosa, ed in
+corrispondenza al tentativo di lettura della risposta. Questo avviene perché
+con UDP non esiste una connessione, e fintanto che non si invia un pacchetto
+non c'è traffico sulla rete. In questo caso l'errore sarà rilevato alla
+ricezione del pacchetto ICMP \textit{destination unreachable} emesso dalla
+macchina cui ci si è rivolti, e questa volta, essendo il socket UDP connesso,
+il kernel potrà riportare detto errore in user space in maniera non ambigua,
+ed esso apparirà alla successiva lettura sul socket.
+
+Si tenga presente infine che l'uso dei socket connessi non risolve l'altro
+problema del client, e cioè il fatto che in caso di perdita di un pacchetto
+questo resterà bloccato permanentemente in attesa di una risposta. Per
+risolvere questo problema l'unico modo sarebbe quello di impostare un
+\textit{timeout} o riscrivere il client in modo da usare l'I/O non bloccante.
+
+\index{socket!locali|(}
+
\section{I socket \textit{Unix domain}}
\label{sec:unix_socket}
-Benché i socket Unix domain non siano strettamente attinenti alla rete, in
-quanto definiscono una interfaccia di comunicazione locale alla singola
-macchina, li tratteremo comunque in questa sezione in quanto la loro
-interfaccia è comunque basata sulla più generale interfaccia dei socket.
+Benché i socket Unix domain, come meccanismo di comunicazione fra processi che
+girano sulla stessa macchina, non siano strettamente attinenti alla rete, li
+tratteremo comunque in questa sezione. Nonostante le loro peculiarità infatti,
+l'interfaccia di programmazione che serve ad utilizzarli resta sempre quella
+dei socket.
+
+
+
+\subsection{Il passaggio di file descriptor}
+\label{sec:sock_fd_passing}
+
+
+
+\index{socket!locali|)}
\section{Altri socket}
\label{sec:socket_other}
-
Tratteremo in questa sezione gli altri tipi particolari di socket supportati
-da Linux, come i \textit{raw socket}, con i quali si possono \textsl{forgiare}
-direttamente i pacchetti a tutti i livelli dello stack dei protocolli, o i
+da Linux, come quelli relativi a particolare protocolli di trasmissione, i
socket \textit{netlink} che definiscono una interfaccia di comunicazione con
-il kernel.
+il kernel, ed i \textit{packet socket} che consentono di inviare pacchetti
+direttamente a livello delle interfacce di rete.
+
+\subsection{I socket \textit{raw}}
+\label{sec:socket_raw}
+
+Tratteremo in questa sezione i cosiddetti \textit{raw socket}, con i quali si
+possono \textsl{forgiare} direttamente i pacchetti a tutti i livelli dello
+stack dei protocolli.
+
+\subsection{I socket \textit{netlink}}
+\label{sec:socket_netlink}
+
+
+\subsection{I \textit{packet socket}}
+\label{sec:packet_socket}
+
%%% mode: latex
%%% TeX-master: "gapil"
%%% End:
+
+% LocalWords: socket cap TCP UDP domain sez NFS DNS stream datagram PF INET to
+% LocalWords: IPv tab SOCK DGRAM three way handshake client fig bind listen AF
+% LocalWords: accept recvfrom sendto connect netstat named DHCP kernel ICMP CR
+% LocalWords: port unreachable read write glibc Specification flags int BSD LF
+% LocalWords: libc unsigned len size tolen sys ssize sockfd const void buf MSG
+% LocalWords: struct sockaddr socklen errno EAGAIN ECONNRESET EDESTADDRREQ RFC
+% LocalWords: EISCONN EMSGSIZE ENOBUFS ENOTCONN EOPNOTSUPP EPIPE SIGPIPE EBADF
+% LocalWords: NOSIGNAL EFAULT EINVAL EINTR ENOMEM ENOTSOCK NULL fromlen from
+% LocalWords: ECONNREFUSED value result argument close shutdown daytime nell'
+% LocalWords: memset inet pton nread NUL superdemone inetd sniffer daytimed
+% LocalWords: INADDR ANY addr echo ClientEcho sendbuff serv VPN tcpdump l'I
+% LocalWords: Stevens destination descriptor raw stack netlink