Questo vuol dire che in generale ciascun programma viene ad agire come un nodo
in una rete potenzialmente paritetica; ciascun programma si trova pertanto a
ricevere ed inviare richieste ed a ricevere ed inviare risposte, e non c'è più
-la separazione netta dei compiti che si ritrova nelle archietetture
+la separazione netta dei compiti che si ritrova nelle architetture
\textit{client-server}.
Le architetture \textit{peer-to-peer} sono salite alla ribalta con
l'esplosione del fenomeno Napster, ma gli stessi protocolli di routing sono un
-buon esempio di archietetture \textit{peer-to-peer}, in cui ciascun nodo,
+buon esempio di architetture \textit{peer-to-peer}, in cui ciascun nodo,
tramite il demone che gestisce il routing, richiede ed invia informazioni ad
altri nodi.
-In realtà in molti casi di archietture classificate come \textit{peer-to-peer}
+In realtà in molti casi di architetture classificate come \textit{peer-to-peer}
non è detto che la struttura sia totalmente paritetica e ci sono parecchi
-esempi in cui alcuni servizi vengono centralizzati o disribuiti
+esempi in cui alcuni servizi vengono centralizzati o distribuiti
gerarchicamente, come per lo stesso Napster, in cui le ricerche venivano
effettuate su un server centrale.
Rispondere a queste esigenze di scalabilità il modello più semplice (chiamato
talvolta \textit{two-tier}) da adottare è stata quello di distribuire il
carico delle richieste su più server identici, mantenendo quindi
-sostanzialmente inalterata l'archiettettura \textit{client-server} originale.
+sostanzialmente inalterata l'architettura \textit{client-server} originale.
Nel far questo ci si scontra però con gravi problemi di manutenibilità dei
servizi, in particolare per quanto riguarda la sincronizzazione dei dati, e di
-inefficienza dell'uso delle risorse. Il problema è particolarmente grave per i
-database che non possono essere replicati e sincronizzati facilemente, e che
-sono molto onerosi sia in termini di richiesta risorse.
+inefficienza dell'uso delle risorse. Il problema è particolarmente grave ad
+esempio per i database che non possono essere replicati e sincronizzati
+facilmente, e che sono molto onerosi, la loro replicazione è costosa e
+complessa.
È a partire da queste problematiche che nasce il modello \textit{three-tier},
-che si struttura, come dice il nome, su tre livelli. Il primo, quello dei
-client, che eseguono le richieste e gestiscono l'interfaccia con l'utente,
+che si struttura, come dice il nome, su tre livelli. Il primo livello, quello
+dei client che eseguono le richieste e gestiscono l'interfaccia con l'utente,
resta sostanzialmente lo stesso del modello \textit{client-server}, ma la
parte server viene suddivisa in due livelli, introducendo un
\textit{middle-tier}, su cui deve appoggiarsi tutta la logica di analisi delle
-richieste dei client per ottimizzare l'accesso al terzo livello, quello dei
-server che invece si limita a fornire dei dati che verranno usati dal
-\textit{middle-tier} per eseguire le operazioni.
+richieste dei client per ottimizzare l'accesso al terzo livello, che è quello
+che si limita a fornire i dati dinamici che verranno usati dalla logica
+implementata nel \textit{middle-tier} per eseguire le operazioni richieste dai
+client.
+In questo modo si può disaccoppiare la logica dai dati, replicando la prima,
+che è molto meno soggetta a cambiamenti ed evoluzione, e non soffre di
+problemi di sincronizzazione, e centralizzando opportunamente i secondi. In
+questo modo si può distribuire il carico ed accedere in maniera efficiente i
+dati.
\section{I protocolli di rete}
che sta per \textit{Department of Defense}), dato che fu sviluppato
dall'agenzia ARPA per il Dipartimento della Difesa Americano.
-\begin{figure}[!htbp]
- \centering
- \includegraphics[width=12cm]{img/iso_tcp_comp}
- \caption{Struttura a livelli dei protocolli OSI e TCP/IP, con la
- relative corrispondenze e la divisione fra kernel e user space.}
- \label{fig:net_osi_tcpip_comp}
-\end{figure}
-
\subsection{Il modello TCP/IP (o DoD)}
\label{sec:net_tcpip_overview}
\figref{fig:net_osi_tcpip_comp} dove viene evidenziata anche la corrispondenza
fra i rispettivi livelli (che comunque è approssimativa) e su come essi vanno
ad inserirsi all'interno di un sistema rispetto alla divisione fra user space
-e kernel space spiegata in \secref{sec:intro_unix_struct}.
+e kernel space spiegata in \secref{sec:intro_unix_struct}.\footnote{in realtà
+ è possibile accedere, attraverso una opportuna interfaccia (come vedremo in
+ \secref{sec:sock_sa_packet}), anche ai livelli inferiori.}
\begin{table}[htb]
\centering
Protocol}) che copre il livello 3 e l'IP (\textit{Internet Protocol}) che
copre il livello 2. Le funzioni dei vari livelli sono le seguenti:
-\begin{description}
-\item \textbf{Applicazione} É relativo ai programmi di interfaccia con la
+\begin{basedescript}{\desclabelwidth{2.5cm}\desclabelstyle{\nextlinelabel}}
+\item[\textbf{Applicazione}] É relativo ai programmi di interfaccia con la
rete, in genere questi vengono realizzati secondo il modello client-server
(vedi \secref{sec:net_cliserv}), realizzando una comunicazione secondo un
protocollo che è specifico di ciascuna applicazione.
-\item \textbf{Trasporto} Fornisce la comunicazione tra le due stazioni
+\item[\textbf{Trasporto}] Fornisce la comunicazione tra le due stazioni
terminali su cui girano gli applicativi, regola il flusso delle
informazioni, può fornire un trasporto affidabile, cioè con recupero degli
errori o inaffidabile. I protocolli principali di questo livello sono il TCP
e l'UDP.
-\item \textbf{Rete} Si occupa dello smistamento dei singoli pacchetti su una
+\item[\textbf{Rete}] Si occupa dello smistamento dei singoli pacchetti su una
rete complessa e interconnessa, a questo stesso livello operano i protocolli
per il reperimento delle informazioni necessarie allo smistamento, per lo
scambio di messaggi di controllo e per il monitoraggio della rete. Il
protocollo su cui si basa questo livello è IP (sia nella attuale versione,
- IPv4 che nella nuova IPv6).
-\item \textbf{Connessione} È responsabile per l'interfacciamento al
+ IPv4, che nella nuova versione, IPv6).
+\item[\textbf{Connessione}] È responsabile per l'interfacciamento al
dispositivo elettronico che effettua la comunicazione fisica, gestendo
- l'invio e la ricezione dall'hardware dei pacchetti.
-\end{description}
+ l'invio e la ricezione dei pacchetti da e verso l'hardware.
+\end{basedescript}
+\begin{figure}[!htb]
+ \centering
+ \includegraphics[width=13cm]{img/iso_tcp_comp}
+ \caption{Struttura a livelli dei protocolli OSI e TCP/IP, con la
+ relative corrispondenze e la divisione fra kernel e user space.}
+ \label{fig:net_osi_tcpip_comp}
+\end{figure}
La comunicazione fra due stazioni remote avviene secondo le modalità
illustrate in \figref{fig:net_tcpip_data_flux}, dove si è riportato il flusso
se in realtà i protocolli di trasmissione usati possono essere molti altri.
\begin{figure}[!htb]
- \centering \includegraphics[width=10cm]{img/tcp_data_flux}
+ \centering \includegraphics[width=12cm]{img/tcp_data_flux}
\caption{Strutturazione del flusso dei dati nella comunicazione fra due
applicazioni attraverso i protocolli della suite TCP/IP.}
\label{fig:net_tcpip_data_flux}
\end{figure}
-La struttura della comunicazione attraverso il TCP/IP si può pertanto
-riassumere nei seguenti passi:
+Per chiarire meglio la struttura della comunicazione attraverso i vari
+protocolli mostrata in \figref{fig:net_tcpip_data_flux}, conviene prendere in
+esame i singoli passaggi fatti per passare da un livello al sottostante,
+la procedura si può riassumere nei seguenti passi:
\begin{itemize}
-\item Le singole applicazioni si scambieranno i dati secondo un loro formato
- specifico, implementando un protocollo di applicazione (esempi possono
- essere HTTP, POP, telnet, SMTP, etc).
-\item Questi dati vengono inviati al livello di trasporto usando
+\item Le singole applicazioni comunicano scambiandosi i dati ciascuna secondo
+ un suo specifico formato. Per applicazioni generiche, come la posta o le
+ pagine web, viene di solito definito ed implementato quello che viene
+ chiamato un protocollo di applicazione (esempi possono essere HTTP, POP,
+ SMTP, ecc.), ciascuno dei quali è descritto in un opportuno standard (di
+ solito attraverso un RFC\footnote{L'acronimo RFC sta per \textit{Request For
+ Comment} ed è la procedura attraverso la quale vengono proposti gli
+ standard per Internet.}).
+\item I dati delle applicazioni vengono inviati al livello di trasporto usando
un'interfaccia opportuna (i \textit{socket}\index{socket}, che esamineremo
- in dettaglio in seguito). Qui verranno spezzati in pacchetti di dimensione
- opportuna e incapsulati nel protocollo di trasporto, aggiungendo ad ogni
- pacchetto le informazioni necessarie per la sua gestione. Questo processo
- viene svolto direttamente nel kernel ad esempio dallo stack TCP nel caso il
- protocollo di trasporto sia questo.
+ in dettaglio in \capref{cha:socket_intro}). Qui verranno spezzati in
+ pacchetti di dimensione opportuna e incapsulati nel protocollo di trasporto,
+ aggiungendo ad ogni pacchetto le informazioni necessarie per la sua
+ gestione. Questo processo viene svolto direttamente nel kernel, ad esempio
+ dallo stack TCP, nel caso il protocollo di trasporto usato sia questo.
\item Una volta composto il pacchetto nel formato adatto al protocollo di
trasporto usato questo sarà passato al successivo livello, quello di rete,
che si occupa di inserire le opportune informazioni per poter effettuare
genere questo è il livello di IP (Internet Protocol), a cui vengono inseriti
i numeri IP che identificano i computer su internet.
\item L'ultimo passo è il trasferimento del pacchetto al driver della
- interfaccia di trasmissione che si incarica di incapsularlo nel relativo
- protocollo di trasmissione fisica usato dall'hardware usato per la
- comunicazione (ad esempio \textit{ethernet} per una scheda di rete).
+ interfaccia di trasmissione, che si incarica di incapsularlo nel relativo
+ protocollo di trasmissione. Questo può avvenire sia in maniera diretta, come
+ nel caso di ethernet, in cui i pacchetti vengono inviati sulla linea
+ attraverso le schede di rete, che in maniera indiretta con protocolli come
+ PPP o SLIP, che vengono usati come interfaccia per far passare i dati su
+ altri dispositivi di comunicazione (come la seriale o la parallela).
\end{itemize}
È il livello di trasporto che si deve occupare (qualora necessiti) del
controllo del flusso dei dati e del recupero degli errori; questo è realizzato
dal protocollo TCP. La sede principale di "intelligenza" della rete è pertanto
-al livello di trasporto o superiore.
+al livello di trasporto o ai livelli superiori.
Infine le singole stazioni collegate alla rete non fungono soltanto da punti
-terminali di comunicazione, ma possono anche assumere il ruolo di router, per
-l'interscambio di pacchetti da una rete ad un'altra. Questo rende possibile la
-flessibilità della rete che è in grado di adattarsi ai mutamenti delle
-interconnessioni.
+terminali di comunicazione, ma possono anche assumere il ruolo di
+\textit{router} (\textsl{instradatori}), per l'interscambio di pacchetti da
+una rete ad un'altra. Questo rende possibile la flessibilità della rete che è
+in grado di adattarsi ai mutamenti delle interconnessioni.
La caratteristica essenziale che rende tutto ciò possibile è la strutturazione
a livelli tramite l'incapsulamento. Ogni pacchetto di dati viene incapsulato
\section{Il protocollo TCP/IP}
\label{sec:net_tpcip}
-Come appena mostrato il protocollo TCP/IP è un insieme di protocolli diversi,
-che operano su 4 livelli diversi. Per gli interessi della programmazione di
-rete però sono importanti principalmente i due livelli centrali, e soprattutto
-quello di trasporto.
+Come accennato in \secref{sec:net_protocols} il protocollo TCP/IP è un insieme
+di protocolli diversi, che operano su 4 livelli diversi. Per gli interessi
+della programmazione di rete però sono importanti principalmente i due livelli
+centrali, e soprattutto quello di trasporto.
-La principale interfaccia di programmazione di rete, quella dei
+La principale interfaccia usata nella programmazione di rete, quella dei
socket\index{socket}, è infatti un'interfaccia nei confronti di quest'ultimo.
Questo avviene perché al di sopra del livello di trasporto i programmi hanno a
che fare solo con dettagli specifici delle applicazioni, mentre al di sotto
vengono curati tutti i dettagli relativi alla comunicazione. È pertanto
-naturale definire una interfaccia di programmazione su questo confine tanto
+naturale definire una interfaccia di programmazione su questo confine, tanto
più che è proprio lì (come evidenziato in \figref{fig:net_osi_tcpip_comp}) che
nei sistemi Unix (e non solo) viene inserita la divisione fra kernel space e
user space.
In realtà in un sistema Unix è possibile accedere anche agli altri livelli
-inferiori (e non solo a quello di trasporto) con opportune interfacce (la cosa
-è indicata in \figref{fig:net_osi_tcpip_comp} lasciando uno spazio fra UDP e
-TCP), ma queste vengono usate solo quando si vogliono fare applicazioni di
-sistema per il controllo della rete a basso livello, un uso quindi molto
-specialistico, e che non rientra in quanto trattato qui.
+inferiori (e non solo a quello di trasporto) con opportune interfacce di
+programmazione (vedi \secref{sec:sock_sa_packet}), ma queste vengono usate
+solo quando si debbano fare applicazioni di sistema per il controllo della
+rete a basso livello, di uso quindi molto specialistico.
-In questa sezione daremo una breve descrizione dei vari protocolli del TCP/IP,
-concentrandoci, per le ragioni esposte sul livello di trasporto. All'interno
-di questo privilegeremo poi il protocollo TCP, per il ruolo centrale che
-svolge nella maggior parte delle applicazioni.
+In questa sezione daremo una descrizione sommaria dei vari protocolli del
+TCP/IP, concentrandoci, per le ragioni appena esposte, sul livello di
+trasporto. All'interno di quest'ultimo privilegeremo poi il protocollo TCP,
+per il ruolo centrale che svolge nella maggior parte delle applicazioni.
\subsection{Il quadro generale}
\label{sec:net_tcpip_general}
Benché si parli di TCP/IP questa famiglia di protocolli è composta anche da
-altri membri. In \figref{fig:net_tcpip_overview} si è riportato uno schema che
+molti membri. In \figref{fig:net_tcpip_overview} si è riportato uno schema che
mostra un panorama sui vari protocolli della famiglia, e delle loro relazioni
reciproche e con alcune dalle principali applicazioni che li usano.
\label{fig:net_tcpip_overview}
\end{figure}
-I vari protocolli mostrati in figura sono i seguenti:
+I vari protocolli riportati in \figref{fig:net_tcpip_overview} sono i
+seguenti:
-\begin{list}{}{}
-\item \textsl{IPv4} \textit{Internet Protocol version 4}. È quello che
+\begin{basedescript}{\desclabelwidth{1.7cm}\desclabelstyle{\nextlinelabel}}
+\item[\textsl{IPv4}] \textit{Internet Protocol version 4}. È quello che
comunemente si chiama IP. Ha origine negli anni '80 e da allora è la base su
- cui è costruita internet. Usa indirizzi a 32 bit e provvede la trasmissione
- dei pacchetti TCP, UDP, ICMP e IGMP.
-\item \textsl{IPv6} \textit{Internet Protocol version 6}. È stato progettato a
- metà degli anni '90 per rimpiazzare IPv4. Ha indirizzi a 128 bit e effettua
- lo stesso servizio di trasporto di IPv4 per i pacchetti TCP, UDP e ICPMv6.
-\item \textsl{TCP} \textit{Trasmission Control Protocol}. È un protocollo
- orientato alla connessione che provvede un trasporto affidabile e
- bidirezionale di un flusso di dati. I socket\index{socket} TCP sono esempi
- di \textit{stream socket}. Il protocollo ha cura di tutti gli aspetti del
- trasporto, come l'acknoweledgment, i timeout, la ritrasmissione, etc. È
- usato dalla maggior parte delle applicazioni. Può essere usato sia con IPv4
- che con IPv6.
-\item \textsl{UDP} \textit{User Datagram Protocol}. È un protocollo senza
- connessione, a pacchetti. I socket\index{socket} UDP sono esempi di
- \textit{datagram socket}. Contrariamente al TCP il protocollo non è
- affidabile e non c'è garanzia che i pacchetti raggiungano la loro
- destinazione, si perdano o vengano duplicati, o abbiano un particolare
- ordine di arrivo. Può essere usato sia con IPv4 che con IPv6.
-\item \textsl{ICMP} \textit{Internet Control Message Protocol}. Gestisce gli
- errori e trasporta l'informazione di controllo fra stazioni remote e
- instradatori (\textit{host} e \textit{router}). I messaggi sono normalmente
- generati dal software del kernel che gestisce la comunicazione TCP/IP, anche
- se ICMP può venire usato direttamente da alcuni programmi come
- \texttt{ping}. A volte ci si riferisce ad esso come ICPMv4 per distinguerlo
- da ICMPv6.
-\item \textsl{IGMP} \textit{Internet Group Management Protocol}. É un
- protocollo usato per il \textit{multicasting} (vedi
- \secref{sec:xxx_multicast}), che è opzionale in IPv4.
-\item \textsl{ARP} \textit{Address Resolution Protocol}. È il protocollo che
- mappa un indirizzo IP in un indirizzo hardware (come un indirizzo
- internet). È usato in reti di tipo broadcast come Ethernet, Token Ring o
- FDDI ma non serve in connessioni punto-punto.
-\item \textsl{RARP} \textit{Reverse Address Resolution Protocol}. È il
- protocollo che mappa un indirizzo hardware in un indirizzo IP. Viene usato a
- volte per durante il boot per assegnare un indirizzo IP ad una macchina.
-\item \textsl{ICMPv6} \textit{Internet Control Message Protocol, version 6}.
+ cui è costruita internet. Usa indirizzi a 32 bit, e mantiene tutte le
+ informazioni di instradamento e controllo per la trasmissione dei pacchetti
+ sulla rete; tutti gli altri protocolli della suite (eccetto ARP e RARP, e
+ quelli specifici di IPv6) vengono trasmessi attraverso di esso.
+\item[\textsl{IPv6}] \textit{Internet Protocol version 6}. È stato progettato
+ a metà degli anni '90 per rimpiazzare IPv4. Ha uno spazio di indirizzi
+ ampliato 128 bit che consente più gerarchie di indirizzi,
+ l'autoconfigurazione, ed un nuovo tipo di indirizzi, gli \textit{anycast},
+ che consentono di inviare un pacchetto ad una stazione su un certo gruppo.
+ Effettua lo stesso servizio di trasmissione dei pacchetti di IPv4 di cui
+ vuole essere un sostituto.
+\item[\textsl{TCP}] \textit{Trasmission Control Protocol}. È un protocollo
+ orientato alla connessione che provvede un trasporto affidabile per un
+ flusso di dati bidirezionale fra due stazioni remote. Il protocollo ha cura
+ di tutti gli aspetti del trasporto, come l'acknoweledgment, i timeout, la
+ ritrasmissione, etc. È usato dalla maggior parte delle applicazioni.
+\item[\textsl{UDP}] \textit{User Datagram Protocol}. È un protocollo senza
+ connessione, per l'invio di dati a pacchetti. Contrariamente al TCP il
+ protocollo non è affidabile e non c'è garanzia che i pacchetti raggiungano
+ la loro destinazione, si perdano, vengano duplicati, o abbiano un
+ particolare ordine di arrivo.
+\item[\textsl{ICMP}] \textit{Internet Control Message Protocol}. È il
+ protocollo usato a livello 2 per gestire gli errori e trasportare le
+ informazioni di controllo fra stazioni remote e instradatori (cioè fra
+ \textit{host} e \textit{router}). I messaggi sono normalmente generati dal
+ software del kernel che gestisce la comunicazione TCP/IP, anche se ICMP può
+ venire usato direttamente da alcuni programmi come \cmd{ping}. A volte ci
+ si riferisce ad esso come ICPMv4 per distinguerlo da ICMPv6.
+\item[\textsl{IGMP}] \textit{Internet Group Management Protocol}. É un
+ protocollo di livello 2 usato per il \textit{multicasting} (vedi
+ \secref{sec:xxx_multicast}). Permette alle stazioni remote di notificare ai
+ router che supportano questa comunicazione a quale gruppo esse appartengono.
+ Come ICMP viene implementato direttamente sopra IP.
+\item[\textsl{ARP}] \textit{Address Resolution Protocol}. È il protocollo che
+ mappa un indirizzo IP in un indirizzo hardware sulla rete locale. È usato in
+ reti di tipo broadcast come Ethernet, Token Ring o FDDI che hanno associato
+ un indirizzo fisico (il \textit{MAC address}) alla interfaccia, ma non serve
+ in connessioni punto-punto.
+\item[\textsl{RARP}] \textit{Reverse Address Resolution Protocol}. È il
+ protocollo che esegue l'operazione inversa rispetto ad ARP (da cui il nome)
+ mappando un indirizzo hardware in un indirizzo IP. Viene usato a volte per
+ durante l'avvio per assegnare un indirizzo IP ad una macchina.
+\item[\textsl{ICMPv6}] \textit{Internet Control Message Protocol, version 6}.
Combina per IPv6 le funzionalità di ICMPv4, IGMP e ARP.
-\item \textsl{NETLINK} \textit{Netlink}. Provvede, in Linux, l'interfaccia di
- accesso alla comunicazione a basso livello.
-\end{list}
+\item[\textsl{EGP}] \textit{Exterior Gateway Protocol}. È un protocollo di
+ routing usato per comunicare lo stato fra gateway vicini a livello di
+ \textsl{sistemi autonomi}\footnote{vengono chiamati \textit{autonomous
+ systems} i raggruppamenti al livello più alto della rete.}, con
+ meccanismi che permettono di identificare i vicini, controllarne la
+ raggiungibilità e scambiare informazioni sullo stato della rete. Viene
+ implementato direttamente sopra IP.
+\item[\textsl{OSPF}] \textit{Open Shortest Path First}. È in protocollo di
+ routing per router su reti interne, che permette a questi ultimi di
+ scambiarsi informazioni sullo stato delle connessioni e dei legami che
+ ciascuno ha con gli altri. Viene implementato direttamente sopra IP.
+\item[\textsl{GRE}] \textit{Generic Routing Encapsulation}. È un protocollo
+ generico di incapsulamento che permette di incapsulare un qualunque altro
+ protocollo all'interno di IP.
+\item[\textsl{AH}] \textit{Authentication Header}. Provvede l'autenticazione
+ dell'integrità e dell'origine di un pacchetto. È una opzione nativa in IPv6
+ e viene implementato come protocollo a sé su IPv4. Fa parte della suite di
+ IPSEC che provvede la trasmissione cifrata ed autenticata a livello IP.
+\item[\textsl{ESP}] \textit{Encapsulating Security Payload}. Provvede la
+ cifratura insieme all'autenticazione dell'integrità e dell'origine di un
+ pacchetto. Come per AH è opzione nativa in IPv6 e viene implementato come
+ protocollo a sé su IPv4.
+\item[\textsl{PPP}] \textit{Point-to-Point Protocol}. È un protocollo a
+ livello 1 progettato per lo scambio di pacchetti su connessioni punto punto.
+ Viene usato per configurare i collegamenti, definire i protocolli di rete
+ usati ed incapsulare i pacchetti di dati. È un protocollo complesso con
+ varie componenti.
+\item[\textsl{SLIP}] \textit{Serial Line over IP}. È un protocollo di livello
+ 1 che permette di trasmettere un pacchetto IP attraverso una linea seriale.
+\end{basedescript}
Gran parte delle applicazioni comunicano usando TCP o UDP, solo alcune, e per
-scopi particolari si rifanno dirattamente ad IP (ed i suoi correlati ICMP e
+scopi particolari si rifanno direttamente ad IP (ed i suoi correlati ICMP e
IGMP); benché sia TCP che UDP siano basati su IP e sia possibile intervenire a
questo livello con i \textit{raw socket} questa tecnica è molto meno diffusa e
a parte applicazioni particolari si preferisce sempre usare i servizi messi a
\label{sec:net_tcp}
Il TCP è un protocollo molto complesso, definito nell'RFC~739 e completamente
-diverso da UDP; alla base del suo design infatti non stanno semplicità e
-velocità, ma la ricerca della massima affidabilità possibile nella
-trasmissione dei dati.
+diverso da UDP; alla base della sua progettazione infatti non stanno
+semplicità e velocità, ma la ricerca della massima affidabilità possibile
+nella trasmissione dei dati.
La prima differenza con UDP è che TCP provvede sempre una connessione diretta
fra un client e un server, attraverso la quale essi possono comunicare; per
(il cosiddetto \textit{acknowlegment}), se questo non arriva essi verranno
ritrasmessi per un determinato numero di tentativi, intervallati da un periodo
di tempo crescente, fino a che sarà considerata fallita o caduta la
-connessione (e generato un errore di \textit{time-out}), dopo un periodo di
-tempo che dipende dall'implementazione e che può variare far i quattro e i
-dieci minuti.
+connessione (e sarà generato un errore di \textit{timeout}); il periodo di
+tempo dipende dall'implementazione e può variare far i quattro e i dieci
+minuti.
-Inoltre per tenere conto delle diverse condizioni in cui può trovarsi la linea
-di comunicazione TCP comprende anche un algoritmo di calcolo dinamico del
-tempo di andata e ritorno dei pacchetti (il cosiddetto RTT,
-\textit{round-trip time}) fra un client e un server che lo rende in grado di
-adattarsi alle condizioni della rete per non generare inutili ritrasmissioni o
-cadere facilmente in timeout.
+Inoltre, per tenere conto delle diverse condizioni in cui può trovarsi la
+linea di comunicazione, TCP comprende anche un algoritmo di calcolo dinamico
+del tempo di andata e ritorno dei pacchetti fra un client e un server (il
+cosiddetto RTT, \textit{round-trip time}), che lo rende in grado di adattarsi
+alle condizioni della rete per non generare inutili ritrasmissioni o cadere
+facilmente in timeout.
Inoltre TCP è in grado di preservare l'ordine dei dati assegnando un numero di
sequenza ad ogni byte che trasmette. Ad esempio se un'applicazione scrive 3000
chiamate \textit{segment}) di 1500 byte, di cui il primo conterrà il numero di
sequenza $1-1500$ e il secondo il numero $1501-3000$. In questo modo anche se
i segmenti arrivano a destinazione in un ordine diverso, o se alcuni arrivano
-più volte a causa di ritrasmissioni dovute alla perdita dei ricevuto,
-all'arrivo sarà comunque possibile riordinare i dati e scartare i duplicati.
+più volte a causa di ritrasmissioni dovute alla perdita degli
+\textit{acknowlegment}, all'arrivo sarà comunque possibile riordinare i dati e
+scartare i duplicati.
Il protocollo provvede anche un controllo di flusso (\textit{flow control}),
cioè specifica sempre all'altro capo della trasmissione quanti dati può
socket\index{socket} ed aumentando con la lettura di quest'ultimo da parte
dell'applicazione, se diventa nulla il buffer di ricezione è pieno e non
verranno accettati altri dati. Si noti che UDP non provvede niente di tutto
-ciò per cui nulla impedisce che vengano trasmessi pacchetti ad un rate che il
+ciò per cui nulla impedisce che vengano trasmessi pacchetti ad un ritmo che il
ricevente non può sostenere.
-Infine attraverso TCP la trasmissione è sempre bidirezionale (in inglese
-\textit{full-duplex}), è cioè possibile sia trasmettere che ricevere allo
-stesso tempo, il che poi comporta che quanto dicevamo a proposito del
-controllo di flusso e della gestione della sequenzialità dei dati viene
+Infine attraverso TCP la trasmissione è sempre bidirezionale (in inglese si
+dice che è \textit{full-duplex}). È cioè possibile sia trasmettere che
+ricevere allo stesso tempo, il che comporta che quanto dicevamo a proposito
+del controllo di flusso e della gestione della sequenzialità dei dati viene
effettuato per entrambe le direzioni di comunicazione.
-Una descrizione più accurata del protocollo è fornita in appendice
-\capref{cha:tcp_protocol}.
+%% Una descrizione più accurata del protocollo è fornita in appendice
+%% \capref{cha:tcp_protocol}.
\subsection{Limiti e dimensioni riguardanti la trasmissione dei dati}
\label{sec:net_lim_dim}
Un elenco di questi limiti, insieme ad un breve accenno alle loro origini ed
alle eventuali implicazioni che possono avere, è il seguente:
\begin{itemize}
-\item La dimensione massima di un pacchetto IP è di 65535 byte, compreso
- l'header. Questo è dovuto al fatto che la dimensione è indicata da un campo
- apposito nell'header di IP che è lungo 16 bit (vedi
+\item La dimensione massima di un pacchetto IP è di 65535 byte, compresa
+ l'intestazione. Questo è dovuto al fatto che la dimensione è indicata da un
+ campo apposito nell'header di IP che è lungo 16 bit (vedi
\figref{fig:IP_ipv4_head}).
\item La dimensione massima di un pacchetto normale di IPv6 è di 65575 byte,
il campo apposito nell'header infatti è sempre a 16 bit, ma la dimensione
suddetto campo. Inoltre IPv6 ha la possibilità di estendere la dimensione di
un pacchetto usando la \textit{jumbo payload option}.
\item Molte reti fisiche hanno un MTU (\textit{maximum transfer unit}) che
- dipende dal protocollo specifico usato al livello di link. Il più comune è
- quello dell'Ethernet che è pari a 1500 byte, una serie di valori possibili
- sono riportati in \tabref{tab:net_mtu_values}.
+ dipende dal protocollo specifico usato al livello di connessione fisica. Il
+ più comune è quello di ethernet che è pari a 1500 byte, una serie di altri
+ valori possibili sono riportati in \tabref{tab:net_mtu_values}.
\end{itemize}
Quando un pacchetto IP viene inviato su una interfaccia di rete e le sue
dimensioni eccedono la MTU viene eseguita la cosiddetta
-\textit{frammentazione}, i pacchetti cioè vengono spezzati (sia da IPv4 che da
-IPv6, anche se i pacchetti frammentati sono gestiti con modalità
-diverse,\footnote{il primo usa un flag nell'header, il secondo una opportuna
- opzione, si veda \secref{cha:ip_protocol}.}) in blocchi più piccoli che
-possono essere trasmessi attraverso l'interfaccia.
+\textit{frammentazione}, i pacchetti cioè vengono suddivisi\footnote{questo
+ accade sia per IPv4 che per IPv6, anche se i pacchetti frammentati sono
+ gestiti con modalità diverse, IPv4 usa un flag nell'header, IPv6 una
+ opportuna opzione, si veda \secref{cha:ip_protocol}.}) in blocchi più
+piccoli che possono essere trasmessi attraverso l'interfaccia.
\begin{table}[!htb]
\centering
Una delle differenze fra IPv4 e IPv6 é che per IPv6 la frammentazione può
essere eseguita solo alla sorgente, questo vuol dire che i router IPv6 non
-frammentano i pacchetti che trasmettono (anche se possono frammentare i
+frammentano i pacchetti che ritrasmettono (anche se possono frammentare i
pacchetti che generano loro stessi), mentre i router IPv4 si. In ogni caso una
volta frammentati i pacchetti possono essere riassemblati solo alla
destinazione.
pacchetto non deve essere frammentato; un router che riceva un pacchetto le
cui dimensioni eccedano quelle dell'MTU della rete di destinazione genererà un
messaggio di errore ICMPv4 di tipo \textit{destination unreachable,
- fragmentation needed but DF bit set}.
-
-Dato che i router IPv6 non possono effettuare la frammentazione la ricezione
-di un pacchetto di dimensione eccessiva per la ritrasmissione genererà sempre
-un messaggio di errore ICMPv6 di tipo \textit{packet too big}.
-
-Dato che il meccanismo di frammentazione e riassemblaggio comporta
-inefficienza, normalmente viene utilizzato il procedimento della \textit{path
- MTU discover} (vedi RFC~1191 per IPv4 e RFC~1981 per IPv6) che permette di
-trovare il \textit{path MTU} fra due stazioni; per la realizzazione del
-procedimento si usa il flag DF di IPv4 e il comportamento normale di IPv6
-inviando delle opportune serie di pacchetti (per i dettagli vedere l'RFC~1191
-per IPv4 e l'RFC~1981 per IPv6) fintanto che non si hanno più errori.
+ fragmentation needed but DF bit set}. Dato che i router IPv6 non possono
+effettuare la frammentazione la ricezione di un pacchetto di dimensione
+eccessiva per la ritrasmissione genererà sempre un messaggio di errore ICMPv6
+di tipo \textit{packet too big}.
+
+Dato che il meccanismo di frammentazione e riassemblaggio dei pacchetti
+comporta inefficienza, normalmente viene utilizzato un procedimento, detto
+\textit{path MTU discovery} che permette di determinare il \textit{path MTU}
+fra due stazioni; per la realizzazione del procedimento si usa il flag DF di
+IPv4 e il comportamento normale di IPv6 inviando delle opportune serie di
+pacchetti (per i dettagli vedere l'RFC~1191 per IPv4 e l'RFC~1981 per IPv6)
+fintanto che non si hanno più errori.
Il TCP usa sempre questo meccanismo, che per le implementazioni di IPv4 è
opzionale, mentre diventa obbligatorio per IPv6. Per IPv6 infatti, non
potendo i router frammentare i pacchetti, è necessario, per poter comunicare,
-conoscere il \textit{path MTU}.
-
+conoscere da subito il \textit{path MTU}.
Infine TCP definisce una \textit{maximum segment size} MSS che annuncia
-all'altro capo la dimensione massima del segmento di dati.
+all'altro capo della connessione la dimensione massima dimensione del segmento
+di dati che può essere ricevuto, così da evitare la frammentazione. Di norma
+viene impostato alla dimensione della MTU dell'interfaccia meno la lunghezza
+delle intestazioni di IP e TCP, in Linux il default, mantenuto nella costante
+\const{TCP\_MSS} è 512.
%\subsection{Il passaggio dei dati in TCP}
\label{sec:sock_socket_def}
I \textit{socket}\footnote{una traduzione letterale potrebbe essere
- \textsl{presa}, ma essendo universalmente noti come socket utilizzeremo
- sempre la parola inglese.} sono uno dei principali meccanismi di
-comunicazione utilizzato in ambito Unix, e li abbiamo brevemente incontrati in
-\secref{sec:ipc_socketpair}, fra i vari meccanismi di intercominazione fra
+ \textsl{presa}, ma essendo universalmente noti come \textit{socket}
+ utilizzeremo sempre la parola inglese.} sono uno dei principali meccanismi
+di comunicazione utilizzato in ambito Unix, e li abbiamo brevemente incontrati
+in \secref{sec:ipc_socketpair}, fra i vari meccanismi di intercominazione fra
processi. Un socket costituisce in sostanza un canale di comunicazione fra due
processi su cui si possono leggere e scrivere dati analogo a quello di una
pipe (vedi \secref{sec:ipc_pipes}) ma, a differenza di questa e degli altri
La flessibilità e la genericità dell'interfaccia inoltre consente di
utilizzare i socket con i più disparati meccanismi di comunicazione, e non
-solo con la suite dei protocolli TCP/IP, anche se questa sarà comunque quella
+solo con l'insieme dei protocolli TCP/IP, anche se questa sarà comunque quella
di cui tratteremo in maniera più estesa.
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 byte, altri
-invece li raggruppano in blocchi (i pacchetti).
+comunicazione considerano i dati come una sequenza continua di byte, in quello
+che viene chiamato un \textsl{flusso} (in inglese \textit{stream}), mentre
+altri invece li raggruppano in \textsl{pacchetti} (in inglese
+\textit{datagram}) che vengono inviati in blocchi separati.
Un'altro esempio di stile concerne la possibilità che la comunicazione possa o
meno perdere dati, possa o meno non rispettare l'ordine in cui essi non sono
É chiaro che ciascuno di questi stili comporta una modalità diversa di gestire
la comunicazione, ad esempio se è inaffidabile occorrerà essere in grado di
-gestire la perdita o il rimescolamento dei dati.
+gestire la perdita o il rimescolamento dei dati, se è a pacchetti questi
+dovranno essere opportunamente trattati, ecc.
\section{La creazione di un \textit{socket}}
\label{sec:sock_socket}
La creazione di un socket avviene attraverso l'uso della funzione
-\funcd{socket}; questa restituisce un \textit{file descriptor}\footnote{del
+\funcd{socket}; essa restituisce un \textit{file descriptor}\footnote{del
tutto analogo a quelli che si ottengono per i file di dati e le pipe,
descritti in \secref{sec:file_fd}.} che serve come riferimento al socket; il
suo prototipo è:
\item[\errcode{EINVAL}] Protocollo sconosciuto o dominio non disponibile.
\item[\errcode{ENOBUFS}] Non c'è sufficiente memoria per creare il socket
(può essere anche \errval{ENOMEM}).
- \end{errlist}}
+ \end{errlist}
+ inoltre, a seconda del protocollo usato, potranno essere generati altri
+ errori, che sono riportati nelle relative pagine di manuale.}
\end{prototype}
La funzione ha tre argomenti, \param{domain} specifica il dominio del socket
-(definisce cioè la famiglia di protocolli, come vedremo in
-\secref{sec:sock_domain}), \param{type} specifica il tipo di socket (definisce
-cioè lo stile di comunicazione, come vedremo in \secref{sec:sock_type}) e
+(definisce cioè, come vedremo in \secref{sec:sock_domain}, la famiglia di
+protocolli usata), \param{type} specifica il tipo di socket (definisce cioè,
+come vedremo in \secref{sec:sock_type}, lo stile di comunicazione) e
\param{protocol} il protocollo; in genere quest'ultimo è indicato
-implicitamente dal tipo di socket, per cui viene messo a zero (con l'eccezione
-dei \textit{raw socket}).
+implicitamente dal tipo di socket, per cui di norma questo valore viene messo
+a zero (con l'eccezione dei \textit{raw socket}).
Si noti che la creazione del socket si limita ad allocare le opportune
strutture nel kernel (sostanzialmente una voce nella \textit{file table}) e
famiglie di protocolli che supportino diverse strutture di indirizzi, per cui
nella pratica questi due nomi sono equivalenti e corrispondono agli stessi
valori numerici.\footnote{in Linux, come si può verificare andando a guardare
- il contenuto di \file{bits/socket.h} le costanti sono esattamente le stesse
+ il contenuto di \file{bits/socket.h}, le costanti sono esattamente le stesse
e ciascuna \texttt{AF\_} è definita alla corrispondente \texttt{PF\_} e con
lo stesso nome.}
definiti; fra questi però saranno utilizzabili solo quelli per i quali si è
compilato il supporto nel kernel (o si sono caricati gli opportuni moduli),
viene definita anche una costante \const{PF\_MAX} che indica il valore
- massimo associabile ad un dominio (nel caso 32).}
+ massimo associabile ad un dominio (nel caso il suo valore 32).}
Si tenga presente che non tutte le famiglie di protocolli sono utilizzabili
dall'utente generico, ad esempio in generale tutti i socket di tipo
bidirezionale, sequenziale e affidabile. Opera su una connessione con un
altro socket. I dati vengono ricevuti e trasmessi come un flusso continuo di
byte (da cui il nome \textit{stream}).
-\item[\const{SOCK\_DGRAM}] Viene usato per mandare pacchetti di lunghezza
- massima fissata (\textit{datagram}) indirizzati singolarmente, senza
- connessione e in maniera non affidabile. È l'opposto del precedente.
+\item[\const{SOCK\_DGRAM}] Viene usato per trasmettere pacchetti di dati
+ (\textit{datagram}) di lunghezza massima fissata indirizzati singolarmente,
+ Non esiste una connessione e la trasmissione è effettuata in maniera non
+ affidabile.
\item[\const{SOCK\_SEQPACKET}] Provvede un canale di trasmissione di dati
bidirezionale, sequenziale e affidabile. Opera su una connessione con un
- altro socket. I dati possono solo essere trasmessi e letti per pacchetti (di
- dimensione massima fissata).
+ altro socket. I dati possono vengono trasmessi per pacchetti di dimensione
+ massima fissata, ed devono essere letti integralmente da ciascuna
+ chiamata a \func{read}.
\item[\const{SOCK\_RAW}] Provvede l'accesso a basso livello ai protocolli di
rete e alle varie interfacce. I normali programmi di comunicazione non
- devono usarlo.
-\item[\const{SOCK\_RDM}] Provvede un canale di trasmissione di pacchetti
- affidabile ma in cui non è garantito l'ordine di arrivo dei pacchetti.
+ devono usarlo, è riservato all'uso di sistema.
+\item[\const{SOCK\_RDM}] Provvede un canale di trasmissione di dati
+ affidabile, ma in cui non è garantito l'ordine di arrivo dei pacchetti.
\item[\const{SOCK\_PACKET}] Obsoleto, non deve essere usato.
\end{basedescript}
vengono utilizzate dalle altre funzioni della interfaccia dei socket, quando
la comunicazione viene effettivamente realizzata. 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 \var{sockaddr\_}, quelli propri di ciascuna famiglia vengono
+sua peculiare struttura degli indirizzi. I nomi di tutte queste strutture
+iniziano per \var{sockaddr\_}; quelli propri di ciascuna famiglia vengono
identificati dal suffisso finale, aggiunto al nome precedente.
Tutte le funzioni dei socket che usano gli indirizzi sono definite usando nel
prototipo un puntatore a questa struttura; per questo motivo quando si
invocano dette funzioni passando l'indirizzo di un protocollo specifico
-occorrerà eseguire una coversione (il \textit{casting}) del relativo
-puntatore.
+occorrerà eseguire una conversione del relativo puntatore.
I tipi di dati che compongono la struttura sono stabiliti dallo standard
POSIX.1g e li abbiamo riassunti in \tabref{tab:sock_data_types} con i
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
-\var{sa\_family} con cui determinare il tipo di indirizzo; per questo
-motivo, anche se l'uso di un puntatore \ctyp{void *} sarebbe più immediato
-per l'utente (che non dovrebbe più eseguire il casting), è stato mantenuto
-l'uso di questa struttura.
+\var{sa\_family}, comune a tutte le famiglie, con cui determinare il tipo di
+indirizzo; per questo motivo, anche se l'uso di un puntatore \ctyp{void *}
+sarebbe più immediato per l'utente (che non dovrebbe più eseguire il casting),
+è stato mantenuto l'uso di questa struttura.
\subsection{La struttura degli indirizzi IPv4}
\end{figure}
L'indirizzo di un socket internet (secondo IPv4) comprende l'indirizzo
-internet di un'interfaccia più un numero di porta. Il protocollo IP non
-prevede numeri di porta, che sono utilizzati solo dai protocolli di livello
-superiore come TCP e UDP. Questa struttura però viene usata anche per i socket
-RAW che accedono direttamente al livello di IP, nel qual caso il numero della
-porta viene impostato al numero di protocollo.
+internet di un'interfaccia più un \textsl{numero di porta} (affronteremo in
+dettaglio il significato di questi numeri in \secref{sec:TCPel_port_num}). Il
+protocollo IP non prevede numeri di porta, che sono utilizzati solo dai
+protocolli di livello superiore come TCP e UDP. Questa struttura però viene
+usata anche per i socket RAW che accedono direttamente al livello di IP, nel
+qual caso il numero della porta viene impostato al numero di protocollo.
Il membro \var{sin\_family} deve essere sempre impostato a \const{AF\_INET},
altrimenti si avrà un errore di \errcode{EINVAL}; il membro \var{sin\_port}
-specifica il \textsl{numero di porta} (affronteremo in dettaglio in le
-\textsl{porte} in \secref{sec:TCPel_port_num}). I numeri di porta sotto il
-1024 sono chiamati \textsl{riservati} in quanto utilizzati da servizi standard
-e soltanto processi con i privilegi di amministratore (con user-ID effettivo
+specifica il \textsl{numero di porta}. I numeri di porta sotto il 1024 sono
+chiamati \textsl{riservati} in quanto utilizzati da servizi standard e
+soltanto processi con i privilegi di amministratore (con user-ID effettivo
uguale a zero) o con la capability \texttt{CAP\_NET\_BIND\_SERVICE} possono
usare la funzione \func{bind} (che vedremo in \secref{sec:TCPel_func_bind}) su
queste porte.
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* Scope id (new in 2.4) */
};
-
struct in6_addr {
uint8_t s6_addr[16]; /* IPv6 address */
};
il campo \var{sin6\_scope\_id} è un campo introdotto in Linux con il kernel
2.4, per gestire alcune operazioni riguardanti il multicasting.
-Si noti che questa struttura è più grande della \struct{sockaddr} generica
-vista in \figref{fig:sock_sa_gen_struct}, quindi occorre stare attenti a non
-avere fatto assunzioni riguardo alla possibilità di contenere i dati nelle
-dimensioni di quest'ultima.
+Si noti che questa struttura ha una dimensione maggiore della struttura
+\struct{sockaddr} generica vista in \figref{fig:sock_sa_gen_struct}, 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 \const{PF\_UNIX} o \const{PF\_LOCAL} vengono usati per una
-comunicazione fra processi che stanno sulla stessa macchina (per vengono
-chiamati \textit{local domain} o anche \textit{Unix domain}); essi rispetto ai
-precedenti possono essere anche creati in maniera anonima attraverso la
-funzione \func{socketpair} (vedi \secref{sec:ipc_socketpair}). Quando però si
-vuole fare riferimento esplicito ad uno di questi socket si deve usare una
-struttura degli indirizzi di tipo \struct{sockaddr\_un}, la cui definizione si
-è riportata in \secref{fig:sock_sa_local_struct}.
+comunicazione fra processi che stanno sulla stessa macchina (per questo
+vengono chiamati \textit{local domain} o anche \textit{Unix domain}); essi
+hanno la caratteristica ulteriore di poter essere creati anche in maniera
+anonima attraverso la funzione \func{socketpair} (che abbiamo trattato in
+\secref{sec:ipc_socketpair}). Quando però si vuole fare riferimento esplicito
+ad uno di questi socket si deve usare una struttura degli indirizzi di tipo
+\struct{sockaddr\_un}, la cui definizione si è riportata in
+\secref{fig:sock_sa_local_struct}.
\begin{figure}[!htb]
\footnotesize \centering
\end{figure}
In questo caso il campo \var{sun\_family} deve essere \const{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 (mantenuta 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 e vengono usati i
-restanti byte come stringa, senza terminazione.
+il campo \var{sun\_path} deve specificare un indirizzo. Questo ha due forme;
+può essere un file (di tipo socket) nel filesystem o una stringa univoca
+(mantenuta 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 e
+vengono usati come nome i restanti byte come stringa, senza terminazione.
\subsection{La struttura degli indirizzi AppleTalk}
uint8_t sat_port; /* port */
struct at_addr sat_addr; /* net/node */
};
-
struct at_addr {
uint16_t s_net;
uint8_t s_node;
inferiori a 129 sono usati per le \textsl{porte riservate}, e possono essere
usati solo da processi con i privilegi di amministratore o con la capability
\const{CAP\_NET\_BIND\_SERVICE}. L'indirizzo remoto è specificato nella
-struttura \var{sat\_addr}, e deve essere in \textit{network order}; esso è
-composto da un parte di rete data dal campo \var{s\_net}, che può assumere il
-valore \const{AT\_ANYNET}, che indica una rete genrica e vale anche per
-indicare la rete su cui si è, il singolo nodo è indicato da \var{s\_node}, e
-può prendere il valore generico \const{AT\_ANYNODE} che indica anche il nodo
-corrente, ed il valore \const{ATADDR\_BCAST} che indica tutti i nodi della
-rete.
+struttura \var{sat\_addr}, e deve essere in \textit{network order} (vedi
+\secref{sec:sock_endianess}); esso è composto da un parte di rete data dal
+campo \var{s\_net}, che può assumere il valore \const{AT\_ANYNET}, che indica
+una rete generica e vale anche per indicare la rete su cui si è, il singolo
+nodo è indicato da \var{s\_node}, e può prendere il valore generico
+\const{AT\_ANYNODE} che indica anche il nodo corrente, ed il valore
+\const{ATADDR\_BCAST} che indica tutti i nodi della rete.
+
+
+\subsection{La struttura degli indirizzi dei \textit{packet socket}}
+\label{sec:sock_sa_packet}
+
+I \textit{packet socket}, identificati dal dominio \const{PF\_PACKET}, sono
+un'interfaccia specifica di Linux per inviare e ricevere pacchetti
+direttamente su un'interfaccia di rete, senza passare per le routine di
+gestione dei protocolli di livello superiore. In questo modo è possibile
+implementare dei protocolli in user space, agendo direttamente sul livello
+fisico. In genere comunque si preferisce usare la libreria \file{pcap}, che
+assicura la portabilità su altre piattaforme, anche se con funzionalità
+ridotte.
+
+Questi socket possono essere di tipo \const{SOCK\_RAW} o \const{SOCK\_DGRAM}.
+Con socket di tipo \const{SOCK\_RAW} si può operare sul livello di
+collegamento, ed i pacchetti vengono passati direttamente dal socket al driver
+del dispositivo e viceversa. In questo modo, in fase di trasmissione, il
+contenuto completo dei pacchetti, comprese le varie intestazioni, deve essere
+fornito dall'utente. In fase di ricezione invece tutto il contenuto del
+pacchetto viene passato inalterato sul socket, anche se il kernel analizza
+comunque il pacchetto, riempiendo gli opportuni campi della struttura
+\struct{sockaddr\_ll} ad esso associata.
+
+Si usano invece socket di tipo \const{SOCK\_DGRAM} quando si vuole operare a
+livello di rete. In questo caso in fase di ricezione l'intestazione del
+protocollo di collegamento viene rimossa prima di passare il resto del
+pacchetto all'utente, mentre in fase di trasmissione viene creata una
+opportuna intestazione per il protocollo a livello di collegamento
+utilizzato, usando le informazioni necessarie che devono essere specificate
+sempre con una struttura \struct{sockaddr\_ll}.
+
+Nella creazione di un \textit{packet socket} il valore dell'argomento
+\param{protocol} di \func{socket} serve a specificare, in \textit{network
+ order}, il numero identificativo del protocollo di collegamento si vuole
+utilizzare. I valori possibili sono definiti secondo lo standard IEEE 802.3, e
+quelli disponibili in Linux sono accessibili attraverso opportune costanti
+simboliche definite nel file \file{linux/if\_ether.h}. Se si usa il valore
+speciale \const{ETH\_P\_ALL} passeranno sul \textit{packet socket} tutti i
+pacchetti, qualunque sia il loro protocollo di collegamento. Ovviamente l'uso
+di questi socket è una operazione privilegiata e può essere effettuati solo da
+un processo con i privilegi di amministratore (user-ID effettivo nullo) o con
+la capability \const{CAP\_NET\_RAW}.
+
+Una volta aperto un \textit{packet socket}, tutti i pacchetti del protocollo
+specificato passeranno attraverso di esso, qualunque sia l'interfaccia da cui
+provengono; se si vuole limitare il passaggio ad una interfaccia specifica
+occorre usare la funzione \func{bind} per agganciare il socket a quest'ultima.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct sockaddr_ll {
+ unsigned short sll_family; /* Always AF_PACKET */
+ unsigned short sll_protocol; /* Physical layer protocol */
+ int sll_ifindex; /* Interface number */
+ unsigned short sll_hatype; /* Header type */
+ unsigned char sll_pkttype; /* Packet type */
+ unsigned char sll_halen; /* Length of address */
+ unsigned char sll_addr[8]; /* Physical layer address */
+};
+ \end{lstlisting}
+ \end{minipage}
+ \caption{La struttura \structd{sockaddr\_ll} degli indirizzi dei
+ \textit{packet socket}.}
+ \label{fig:sock_sa_packet_struct}
+\end{figure}
+
+Nel caso dei \textit{packet socket} la struttura degli indirizzi è di tipo
+\struct{sockaddr\_ll}, e la sua definizione è riportata in
+\figref{fig:sock_sa_packet_struct}; essa però viene ad assumere un ruolo
+leggermente diverso rispetto a quanto visto finora per gli altri tipi di
+socket. Infatti se il socket è di tipo \const{SOCK\_RAW} si deve comunque
+scrivere tutto direttamente nel pacchetto, quindi la struttura non serve più a
+specificare gli indirizzi. Essa mantiene questo ruolo solo per i socket di
+tipo \const{SOCK\_DGRAM}, per i quali permette di specificare i dati necessari
+al protocollo di collegamento, mentre viene sempre utilizzata in lettura (per
+entrambi i tipi di socket), per la ricezione dei i dati relativi a ciascun
+pacchetto.
+
+Al solito il campo \var{sll\_family} deve essere sempre impostato al valore
+\const{AF\_PACKET}. Il campo \var{sll\_protocol} indica il protocollo scelto,
+e deve essere indicato in \textit{network order}, facendo uso delle costanti
+simboliche definite in \file{linux/if\_ether.h}. Il campo \var{sll\_ifindex} è
+l'indice dell'interfaccia, che, in caso di presenza di più interfacce dello
+stesso tipo (se ad esempio si hanno più schede ethernet), permette di
+selezionare quella con cui si vuole operare (un valore nullo indica qualunque
+interfaccia). Questi sono i due soli campi che devono essere specificati
+quando si vuole selezionare una interfaccia specifica, usando questa struttura
+con la funzione \func{bind}.
+
+I campi \var{sll\_halen} e \var{sll\_addr} indicano rispettivamente
+l'indirizzo associato all'interfaccia sul protocollo di collegamento e la
+relativa lunghezza; ovviamente questi valori cambiano a seconda del tipo di
+collegamento che si usa, ad esempio, nel caso di ethernet, questi saranno il
+MAC address della scheda e la relativa lunghezza. Essi vengono usati, insieme
+ai campi \var{sll\_family} e \var{sll\_ifindex} quando si inviano dei
+pacchetti, in questo caso tutti gli altri campi devono essere nulli.
+
+Il campo \var{sll\_hatype} indica il tipo ARP, come definito in
+\file{linux/if\_arp.h}, mentre il campo \var{sll\_pkttype} indica il tipo di
+pacchetto; entrambi vengono impostati alla ricezione di un pacchetto ed han
+senso solo in questo caso. In particolare \var{sll\_pkttype} può assumere i
+seguenti valori: \var{PACKET\_HOST} per un pacchetto indirizzato alla macchina
+ricevente, \var{PACKET\_BROADCAST} per un pacchetto di broadcast,
+\var{PACKET\_MULTICAST} per un pacchetto inviato ad un indirizzo fisico di
+multicast, \var{PACKET\_OTHERHOST} per un pacchetto inviato ad un'altra
+stazione (e ricevuto su un'interfaccia in modo promiscuo),
+\var{PACKET\_OUTGOING} per un pacchetto originato dalla propria macchina che
+torna indietro sul socket.
+
+Si tenga presente infine che in fase di ricezione, anche se si richiede il
+troncamento del pacchetto, le funzioni \func{recvmsg}, \func{recv} e
+\func{recvfrom} restituiranno comunque la lunghezza effettiva del pacchetto
+così come arrivato sulla linea.
+
%% \subsection{La struttura degli indirizzi DECnet}
%% \label{sec:sock_sa_decnet}
Converte l'intero a 16 bit \param{netshort} dal formato della rete a quello
della macchina.
- \bodydesc{Tutte le funzioni restituiscono il valore convertito, e non hanno
- errori.}
+ \bodydesc{Tutte le funzioni restituiscono il valore convertito, e non
+ prevedono errori.}
\end{functions}
I nomi sono assegnati usando la lettera \texttt{n} come mnemonico per indicare
% \end{figure}
Entrambe le funzioni accettano l'argomento \param{af} che indica il tipo di
-indirizzo e può essere soltanto \const{AF\_INET} o \const{AF\_INET6}. La prima
-funzione è \funcd{inet\_pton}, che serve a convertire una stringa in un
-indirizzo, il suo prototipo è:
+indirizzo, e che può essere soltanto \const{AF\_INET} o \const{AF\_INET6}. La
+prima funzione, \funcd{inet\_pton}, serve a convertire una stringa in un
+indirizzo; il suo prototipo è:
\begin{prototype}{sys/socket.h}
{int inet\_pton(int af, const char *src, void *addr\_ptr)}
La funzione converte la stringa indicata tramite \param{src} nel valore
numerico dell'indirizzo IP del tipo specificato da \param{af} che viene
-memorizzato all'indirizzo puntato da \param{addr\_ptr}, la funzione restituisce
-un valore positivo in caso di successo, e zero se la stringa non rappresenta
-un indirizzo valido, e negativo se \param{af} specifica una famiglia di
-indirizzi non valida.
+memorizzato all'indirizzo puntato da \param{addr\_ptr}, la funzione
+restituisce un valore positivo in caso di successo, nullo se la stringa non
+rappresenta un indirizzo valido, e negativo se \param{af} specifica una
+famiglia di indirizzi non valida.
-La seconda funzione è \funcd{inet\_ntop} che converte un indirizzo in una
-stringa; il suo prototipo è:
+La seconda funzione di conversione è \funcd{inet\_ntop} che converte un
+indirizzo in una stringa; il suo prototipo è:
\begin{prototype}{sys/socket.h}
{char *inet\_ntop(int af, const void *addr\_ptr, char *dest, size\_t len)}
Converte l'indirizzo dalla relativa struttura in una stringa simbolica.
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, ritorniamo con maggiori dettagli
-su una caratteristica delle funzioni di I/O che nel caso dei socket è
+su una caratteristica delle funzioni di I/O, già accennata in
+\secref{sec:file_read} e \secref{sec:file_write}, che nel caso dei socket è
particolarmente rilevante, e che ci tornerà utile anche in seguito.
\subsection{Il comportamento delle funzioni di I/O}
\label{sec:sock_io_behav}
-Una cosa di cui non sempre si è consapevoli quando si ha a che fare con i
-socket è che le funzioni di input/output non sempre hanno lo stesso
-comportamento che avrebbero con i normali files (in particolare questo accade
-per i socket di tipo stream).
+Una cosa che si tende a dimenticare quando si ha a che fare con i socket è che
+le funzioni di input/output non sempre hanno lo stesso comportamento che
+avrebbero con i normali file di dati (in particolare questo accade 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 byte minore di
quello richiesto. Come già accennato in \secref{sec:file_read} questo è un
-comportamento normale per l'I/O su file; con i normali file di dati il
-problema si avverte solo quando si incontra la fine del file, ma in generale
-non è così.
+comportamento normale per l'I/O su file, ma con i normali file di dati il
+problema si avverte solo quando si incontra la fine del file, in generale non
+è così, e con i socket questo è particolarmente evidente.
-In questo caso tutto quello che il programma chiamante deve fare è di ripetere
-la lettura (o scrittura) per la quantità di byte rimanenti (e le funzioni si
-possono bloccare se i dati non sono disponibili): è lo stesso comportamento
-che si può avere scrivendo più di \const{PIPE\_BUF} byte in una pipe (si
-riveda quanto detto in \secref{sec:ipc_pipes}).
+Quando ci si trova ad affrontare questo comportamento tutto quello che si deve
+fare è semplicemente ripetere la lettura (o la scrittura) per la quantità di
+byte restanti, tenendo conto che le funzioni si possono bloccare se i dati non
+sono disponibili: è lo stesso comportamento che si può avere scrivendo più di
+\const{PIPE\_BUF} byte in una pipe (si riveda quanto detto in
+\secref{sec:ipc_pipes}).
\begin{figure}[htb]
\centering
return (count - nleft);
}
\end{lstlisting}
- \caption{Funzione \func{FullRead}, legge \var{count} byte da un socket }
+ \caption{Funzione \func{FullRead}, legge esattamente \var{count} byte da un
+ file descriptor, iterando opportunamente le letture.}
\label{fig:sock_FullRead_code}
\end{figure}
Per questo motivo, seguendo l'esempio di W. R. Stevens in \cite{UNP1}, si sono
-definite due funzioni \func{FullRead} e \func{FullWrite} che eseguono la
-lettura da un socket tenendo conto di questa caratteristica, ed in grado di
+definite due funzioni, \func{FullRead} e \func{FullWrite}, che eseguono
+lettura e scrittura tenendo conto di questa caratteristica, ed in grado di
ritornare dopo avere letto o scritto esattamente il numero di byte
-specificato; il sorgente è riportato in \figref{fig:sock_FullRead_code} e
-\figref{fig:sock_FullWrite_code} ed è disponibile fra i sorgenti allegati alla
-guida nei files \file{FullRead.c} e \file{FullWrite.c}.
+specificato; il sorgente è riportato rispettivamente in
+\figref{fig:sock_FullRead_code} e \figref{fig:sock_FullWrite_code} ed è
+disponibile fra i sorgenti allegati alla guida nei file \file{FullRead.c} e
+\file{FullWrite.c}.
\begin{figure}[htb]
\centering