X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=othersock.tex;h=9ffb653055bd8489538494dc8e588405d0ca2ff8;hp=9af54ba66d3c073b214a3e731ce86d9f96f1435e;hb=ff76d56c6a2c280cbe4f153173488871d7b12336;hpb=b9b609733592f0013892cc95e223386282ae6d57 diff --git a/othersock.tex b/othersock.tex index 9af54ba..9ffb653 100644 --- a/othersock.tex +++ b/othersock.tex @@ -1,20 +1,21 @@ %% 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} @@ -54,10 +55,11 @@ utilizzando per il tipo di socket il valore \const{SOCK\_DGRAM}. 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 @@ -130,11 +132,11 @@ la destinazione dei dati trasmessi o ottenere l'origine dei dati ricevuti. La 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} @@ -211,7 +213,7 @@ come maschera binaria che permette di impostare una serie di modalit 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. @@ -219,9 +221,9 @@ La seconda funzione utilizzata nella comunicazione fra socket UDP \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} @@ -264,9 +266,10 @@ I due argomenti \param{from} e \param{fromlen} sono utilizzati per ottenere 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 @@ -321,9 +324,9 @@ Il passo successivo (\texttt{\small 13--21}) 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. @@ -656,8 +659,8 @@ asincroni. 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 @@ -666,12 +669,12 @@ le normali funzioni \func{read} e \func{write}.\footnote{in realt 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 usa un socket connesso, venendo meno l'ambiguità segnalata alla fine di sez.~\ref{sec:UDP_problems}, tutti gli eventuali errori asincroni @@ -693,7 +696,7 @@ illustrate in fig.~\ref{fig:UDP_echo_conn_cli}. 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 parametro e sostituendo le +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}. @@ -708,28 +711,79 @@ fig.~\ref{fig:UDP_echo_conn_echo_client}. \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} + @@ -738,3 +792,16 @@ il kernel. %%% 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