From 7502f301c66ac19b976087d4e0fb71807c051791 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 29 Feb 2004 18:00:22 +0000 Subject: [PATCH] Cominciato a scrivere qualcosa ... --- img/udp_connection.dia | Bin 1380 -> 1411 bytes othersock.tex | 234 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 209 insertions(+), 25 deletions(-) diff --git a/img/udp_connection.dia b/img/udp_connection.dia index c681fab8b6210ff6076a7828610cd616890d87e3..d44c6c38e47957ba1dfec004609f6dde29c48c4e 100644 GIT binary patch literal 1411 zcmV-}1$_D+iwFP!000001MOT}Z{j!^A{Wu=>Q!*{Do8S1FfKSEqO4}b zSd06w8n~W(sUBeL{p_C-y%5@b^IT31yYicCTHp>R5yk1=QUdQB@3JEw<5u-Kc8}Z+FskgT|;0^2Sd4Y}o#bdEC z?}tD%LOkl-^}e%LV^>MYI)X$G#$V>4dx{20VUqny{#meH5CN+Xiw2h|qfYo}RFuu- z?h&2FcqT&IV>};@8K>nu-;GI`f{Z%KX6+J^(?a+Rlj%&< zOE-bnO!|oN2=h~$H-XvE_k>EX4-cVU0rnK?xS@(<##Y0M`t)?Nt|pbi4o{5%20H;5 z2$Vw%0)GcFdCV8USW~M$9%aFP>ifBGzgBArCo!?-QBhk!j|V{HRa`Zk%R?2KY(fC3e!xPs&hU+MI>ze zj4w$9Fi<_)vVdv(un$uZK+g)VWVV%HF8!@%TM8=Da@6VJ zmP(okI!KpZ-%*_|Qx&evl@@T*+dx;q5z>a231@TNxvJrbQrP_rJYjx3Py9(JuHcEV z{d~()Jm0c`8$c(NTC(5wX}#+OzKoJE^xTG;$Bfb;rcq|eS@zWw;EkzL2FZ9)+(6YM zQ|AbcEcIZ2*L0C4h8mN9#A7~K%>L7$&Btl<(BJ>@p#eKt|=UDv^ z_!q!n$-WwxhE08-G5D)su%>5)Ru?y0eZ@~?IO&Mj1EG`NYlTvsW9hC{-)}vPJAJ=Z zDN)$n5QX}uGO_~sjVS_4KbN6-LO+*rF`jTbnS!hBtTz)+Sx-O<*fvaiY)2D?9)lML z9(oL}kSW|wm?Bhvzbpi9#uTo@Zeh5qn} zVy3WkS#dF@@H=7(Pc>6m>6jvYZZCv(`T>$FV2Tl;k>&}NJmG1cIF~2#*V+G2dAvFJ RCo7LP{{w?$4~Se%000}RvmXEe literal 1380 zcmV-q1)KUGiwFP!000001MOT{Z{s!)e$THElvhU>3;zl!OceeJoMt~w)For9FXQoMv(e&h3K^kV9Idq!jsJyl498q( ztUlc-%0~qOWH7r{UWJU&XtriZ!7xD+bq41zAth@ZsD)H1HzzTn$}5Z~>ir^rspC@3 z_(0DQ-76TP8Ab4=UA4|%zTZXl3el?CWJS`5i?HpgCeorOd;cI)N~K%~hfnvvSog(} z$_sm4O$%)`!V*Zs2-ofKy@`vBFf`9FjNLw5Zek|hL@eF}6>lO+rz=7kg%PWpnGq5r zhzm=Mu2FY8=^Vy9WRAH4x@%uVjFA)TU%)s$$ARMVJ9;ifVo0OlI1mpcTC{AUfGwwQ z$F@t?dK`P9e=AJ?Ym`Q_7&UniVb=S+cj~vpsIQ(-&dB?Z_l$@_TPx)U9mG1q; zAPyi6ln3QIc~ke51g|5aV50t^A8t?8A+C(GUu}O@WFJJDF#=VG>y*)^d^W4gk<$lzC=;DWbN8@ z&FQ9nMreTOsm1G>-f{2KCD}|HipSHLv>EZ^eXw_qelSS%Yo74<2b#N&f8GUL0RUaS z`tcC(Kjvi#fgJ>%(Hm>PfYBEN{4ja6SVA%2>!xjFS-|56cr-L0=!ThP0uGCAhFP{7 zC#sx^OxvmEt=@rLr7N7r5yGscGdxmywbk+jvnF%db!7pQDBki_AsQ`IC1u;JNZ^NE zeD*m?Q2OvENg)1M&0M~S8VDPaV)rw07|w2S3Z0nK|q8Q$$MUFX+k?F(+#pWz7ZJ z)QRHP;+NMT2~#vl)PnA3APM8sl7ux3NjO&^2}3ijj3mG)8x!6DO&}aFB56V(O*oP! z2BwMT-rMfodxNa@6WMkE&3vCd0h1HNHHJ?;ypq$Wo0>j3!yrKH_^H4^F@M@&K>Prz zmt%4Qbz2iCw>J)W))qa2GBn+E!TSh`Ljkysb2B5T6j8qKas(xyY^+D0oI#1C3vYn5 z>5MGVX)`lnTaP?CY?miZo9E2WPZQjY*99es>@dYpMJ@7v2CC41JXQQ2Vbnkse*a07 zBX|;JYPJU~pIgblKW3$`!9fOW#i~z68 z{H`tbMTyX>JkQ%Wl7bs4FxP8k&`jd)=&a&2Ni(vTc=ZYc1~N zjZvXQG00O^-c_Em;uZ2cQ&{o=3ds|me9r1>JYfwo3Ae>h!tHVrZkoU!IX6*KNTLuu z2e;)M{Ax^L55g4Po8R-P!p{nd-AyxY(30(kWQ$ttNxBe97tSDbVTfl7P_ji{SQxj_ mfylq~5KI+@WQxm~qWC%gZv#(v2mg-X>Fz(`MWnfgNB{s+?~+6S diff --git a/othersock.tex b/othersock.tex index d7bc4c0..868ca66 100644 --- a/othersock.tex +++ b/othersock.tex @@ -29,30 +29,34 @@ principali e le modalit \label{sec:UDP_characteristics} Come illustrato in \secref{sec:net_udp} UDP è un protocollo molto semplice che -non supporta le connessioni e non è affidabile: i dati vengono inviati in -forma di pacchetti, e non ne è assicurata né la effettiva ricezione né -l'odinamento. +non supporta le connessioni e non è affidabile: esso si appoggia direttamente +sopra IP (per i dettagli sul protocollo si veda \secref{sec:udp_protocol}). I +dati vengono inviati in forma di pacchetti, e non ne è assicurata né la +effettiva ricezione né l'arrivo nell'ordine in cui vengono inviati. Il +vantaggio del protocollo è la velocità, non è necessario trasmettere le +informazioni di controllo ed il risultato è una trasmissione di dati più +veloce ed immediata. Questo significa che a differenza dei socket TCP i socket UDP non supportano una comunicazione di tipo \textit{stream} in cui si ha a disposizione un -flusso continuo di dati che può essere letto un po' alla volta, ma di tipo -\textit{datagram}, in cui i dati arrivano in singoli blocchi che devono essere -letti integralmente. - -Questo diverso comportamento significa anche che i socket UDP, pur restando -nella famiglia \const{PF\_INET}\footnote{o \const{PF\_INET6} qualora si usasse - invece il protocollo IPv6.} devono essere aperti quando si usa la funzione -\func{socket} (si riveda quanto illustrato a suo tempo in -\tabref{tab:sock_sock_valid_combinations}) utilizzando come valore per il tipo -di socket \const{SOCK\_DGRAM}. - -Questa differenza comporta ovviamente il fatto che anche le modalità con cui -si usano i socket UDP sono completamente diverse rispetto ai socket TCP, ed in +flusso continuo di dati che può essere letto un po' alla volta, ma piuttosto +una comunicazione di tipo \textit{datagram}, in cui i dati arrivano in singoli +blocchi che devono essere letti integralmente. + +Questo diverso comportamento significa anche che i socket UDP, pur +appartenendo alla famiglia \const{PF\_INET}\footnote{o \const{PF\_INET6} + qualora si usasse invece il protocollo IPv6, che pure supporta UDP.} devono +essere aperti quando si usa la funzione \func{socket} (si riveda quanto +illustrato a suo tempo in \tabref{tab:sock_sock_valid_combinations}) +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 di 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 \figref{fig:UDP_packet-exchange}. +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 \figref{fig:UDP_packet-exchange}. \begin{figure}[htb] \centering @@ -62,20 +66,200 @@ schema illustrato in \figref{fig:UDP_packet-exchange}. \label{fig:UDP_packet-exchange} \end{figure} -Anche se UDP è completamente diverso rispetto a TCP resta identica +Come illustrato in \figref{fig:UDP_packet-exchange} la struttura generica di +un server UDP prevede, una volta creato il socket, la chiamata a \func{bind} +per mettersi in ascolto dei dati. Questa è l'unica parte comune con un server +TCP: non essendovi il concetto di connessione le funzioni \func{listen} ed +\func{accept} non sono mai utilizzate nel caso di server UDP. La ricezione dei +dati dal client avviene attraverso la funzione \func{recvfrom}, mentre una +eventuale risposta sarà inviata con la funzione \func{sendto}. + +Da parte del client invece, una volta creato il socket non sarà necessario +connettersi con \func{connect} (anche se, come vedremo in +\secref{sec:UDP_connect}, è possibile usare questa funzione, con un +significato comunque diverso) ma si potrà effettuare direttamente una +richiesta inviando un pacchetto con la funzione \func{sendto} e si potrà +leggere una eventuale risposta con la funzione \func{recvfrom}. +Anche se UDP è completamente diverso rispetto a TCP resta identica la +possibilità di gestire più canali di comunicazione fra due macchine +utilizzando le porte. In questo caso il server dovrà usare comunque la +funzione \func{bind} per scegliere la porta su cui ricevere i dati, e come nel +caso dei socket TCP si potrà usare il comando \cmd{netstat}\footnote{per + ottenere il risultato mostrato occorre usare le opzioni \texttt{-anu}.} per +verificare quali socket sono in ascolto: +\begin{verbatim} +Active Internet connections (servers and established) +Proto Recv-Q Send-Q Local Address Foreign Address State +udp 0 0 0.0.0.0:32768 0.0.0.0:* +udp 0 0 192.168.1.2:53 0.0.0.0:* +udp 0 0 127.0.0.1:53 0.0.0.0:* +udp 0 0 0.0.0.0:67 0.0.0.0:* +\end{verbatim} +in questo caso abbiamo attivi il DNS (sulla porta 53, e sulla 32768 per la +connessione di controllo del server \cmd{named}) ed un server DHCP (sulla +porta 67). + +Si noti però come in questo caso la colonna che indica lo stato sia vuota. I +socket UDP infatti non hanno uno stato. Inoltre anche in presenza di traffico +non si avranno indicazioni delle connessioni attive, proprio perché non esiste +niente di simile per i socket UDP, il kernel si limita infatti a ricevere i +pacchetti ed inviarli al processo in ascolto sulla porta cui essi sono +destinati, oppure a scartarli inviando un messaggio \textit{ICMP port + unreachable} qualora non vi sia nessun processo in ascolto. \subsection{Le funzioni \func{sendto} e \func{recvfrom}} \label{sec:UDP_sendto_recvfrom} -Come accennato le due funzioni principali usate per la trasmissione di dati -attraverso i socket UDP, ma in generale attraverso qualunque socket che -preveda una comunicazione a pacchetti, sono \func{sendto} e \func{recvfrom}. +Come accennato in \secref{sec:UDP_characteristics} le due funzioni principali +usate per la trasmissione di dati attraverso i socket UDP, sono \func{sendto} +e \func{recvfrom}. La necessità di usare queste funzioni è dovuta al fatto che +non esistendo con UDP il concetto di connessione, non si ha neanche a +disposizione un \textsl{socket connesso} su cui sia possibile usare +direttamente \func{read} e \func{write} avendo già stabilito (grazie alla +chiamata ad \func{accept} che lo associa ad una connessione) quali sono +sorgente e destinazione dei dati. + +Per questo motivo nel caso di UDP diventa essenziale utilizzare queste due +funzioni, che sono comunque usabili in generale per la trasmissione di dati +attraverso qualunque tipo di socket, dato che esse hanno la caratteristica di +provvedere tre argomenti aggiuntivi che consentono di specificare destinazione +o origine dei dati trasmessi. La prima delle due 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 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}.} è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/socket.h} + + \funcdecl{ssize\_t sendto(int sockfd, const void *buf, size\_t len, int + flags, const struct sockaddr *to, socklen\_t tolen)} + + Trasmette un messaggio ad un altro socket. + + \bodydesc{La funzione restituisce il numero di caratteri inviati in caso di + successo e -1 per un errore; nel qual caso \var{errno} viene impostata al + rispettivo codice di errore: + \begin{errlist} + \item[\errcode{EAGAIN}] il socket è in modalità non bloccante, ma + l'operazione richede che la funzione si blocchi. + \item[\errcode{ECONNRESET}] l'altro capo della comunicazione ha resettato la + conessione. + \item[\errcode{EDESTADDRREQ}] il socket non è di tipo connesso, e non si è + specificato un indirizzo di destinazione. + \item[\errcode{EISCONN}] il socket è già connesso, ma si è specificato un + destinatario. + \item[\errcode{EMSGSIZE}] il tipo di socket richiede l'invio dei dati in un + blocco unico, ma la dimensione del messaggio lo rende impossibile. + \item[\errcode{ENOBUFS}] la coda di uscita dell'interfaccia è già piena (di + norma Linux non usa questo messaggio ma scarta silenziosamente i + pacchetti). + \item[\errcode{ENOTCONN}] il socket non è connesso e non si è specificata + una destinazione. + \item[\errcode{EOPNOTSUPP}] il valore di \param{flag} non è appropriato per + il tipo di socket usato. + \item[\errcode{EPIPE}] il capo locale della connessione è stato chiuso, si + riceverà anche un segnale di \const{SIGPIPE}, a meno di non aver impostato + \const{MSG\_NOSIGNAL} in \param{flags}. + \end{errlist} + ed anche \errval{EFAULT}, \errval{EBADF}, \errval{EINVAL}, \errval{EINTR}, + \errval{ENOMEM}, \errval{ENOTSOCK} più gli eventuali altri errori relativi + ai protocolli utilizzati.} +\end{functions} + +I primi tre argomenti sono identici a quelli della funzione \func{write} e +specificano il socket \param{sockfd} a cui si fa riferimento ed il buffer +\param{buf} (e relativa lunghezza \param{len}) che contiene i dati da inviare. +Come per \func{write} la funzione ritorna il numero di byte inviati; nel caso +di UDP però questo deve sempre corrispondere alla dimensione totale +specificata da \param{len} in quanto i dati vengono sempre inviati in forma di +pacchetto e non possono essere spezzati in invii successivi. Qualora non ci +sia spazio nel buffer di uscita la funzione si blocca (a meno di non avere +aperto il socket in modalità non bloccante), se invece non è possibile inviare +il messaggio all'interno di un unico pacchetto essa fallisce con l'errore di +\errcode{EMSGSIZE}. + +I due argomenti \param{to} e \param{tolen} servono a specificare la +destinazione del messaggio da inviare, e prendono l'indirizzo di quest'ultima, +nella stessa forma in cui lo si specificherebbe per \func{connect}: \param{to} +deve cioè contere l'indirizzo IP e la porta di destinazione cui si vogliono +inviare i dati e \param{tolen} la relativa dimensione. + +Se il socket è di un tipo che prevede le connessioni, questo deve essere già +connesso prima di eseguire la funzione (altrimenti si avrà un errore di +\errcode{ENOTCONN}) ed inoltre questi due ultimi argomenti devono essere +inizializzati rispettivamente a \const{NULL} e 0 (di solito vengono ignorati, +ma si potrebbe ricevere altrimenti anche un errore di \errcode{EISCONN}). + +Infine l'argomento \param{flags} è un intero usato come maschera binaria che +permette di impostare una serie di modalità di 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 \secref{sec:xxx_sendmsg}, per il momento ci si può limitare ad +usare sempre un valore nullo. + +La seconda funzione utilizzata nella comunicazione fra socket UDP è +\funcd{recvfrom} che serve invece 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 \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 \acr{libc4} e le \acr{libc5}.} è: +\begin{functions} + \headdecl{sys/types.h} + \headdecl{sys/socket.h} + + \funcdecl{ssize\_t recvfrom(int sockfd, const void *buf, size\_t len, int + flags, const struct sockaddr *from, socklen\_t *fromlen)} + + Riceve un messaggio ad un altro socket. + + \bodydesc{La funzione restituisce il numero di byte ricevuti in caso di + successo e -1 in caso di errore; nel qual caso \var{errno} assumerà il + valore: + \begin{errlist} + \item[\errcode{EAGAIN}] il socket è in modalità non bloccante, ma + l'operazione richede che la funzione si blocchi, oppure si è impostato un + timeout in ricezione e questo è scaduto. + \item[\errcode{ECONNREFUSED}] l'altro capo della comunicazione ha rifiutato + la connessione (in genere perché il relativo servizio non è disponibile). + \item[\errcode{ENOTCONN}] il socket è di tipo connesso, ma non si è eseguita + la connessione. + \end{errlist} + ed anche \errval{EFAULT}, \errval{EBADF}, \errval{EINVAL}, \errval{EINTR}, + \errval{ENOMEM}, \errval{ENOTSOCK} più gli eventuali altri errori relativi + ai protocolli utilizzati.} +\end{functions} + +Come per \func{sendto} i primi tre argomenti sono identici agli analoghi di +\func{read}: dal socket vengono letti \param{len} byte che vengono salvati nel +buffer \param{buf}. A seconda del tipo di socket (se di tipo \textit{datagram} +o \textit{stream}) inoltre i byte in eccesso che non sono stati letti possono +rispettivamente andare persi o restare disponibili per una lettura +successiva. + + + + + +\subsection{L'uso della funzione \func{connect} con i socket UDP} +\label{sec:UDP_connect} + +Come illustrato in \secref{sec:UDP_characteristics} essendo i socket UDP privi +di connessione non è necessario per i client usare \func{connect} prima di +iniziare una comunicazione con un server. + \section{I socket \textit{Unix domain}} -\label{sec:UDP_socket} +\label{sec:unix_socket} Benché i socket Unix domain non siano strattamente attinenti alla rete, in quanto definiscono una interfaccia di comunicazione locale alla singola -- 2.30.2