Revisione di parecchia roba sulle reti, rimessi insieme gli esempi ed una
[gapil.git] / socket.tex
index 8c8440f3c9befbd1c9b411b39b2846f5b0e7abb0..06831e7ba290f3b0a4cdf460b9de4e6f2ee888c5 100644 (file)
@@ -446,7 +446,7 @@ si usa IPv4) 
 
 L'indirizzo di un socket internet (secondo IPv4) comprende l'indirizzo
 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
+dettaglio il significato di questi numeri in \secref{sec:TCP_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
@@ -458,15 +458,15 @@ 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
+usare la funzione \func{bind} (che vedremo in \secref{sec:TCP_func_bind}) su
 queste porte.
 
 Il membro \var{sin\_addr} contiene un indirizzo internet, e viene acceduto sia
 come struttura (un resto di una implementazione precedente in cui questa era
 una \direct{union} usata per accedere alle diverse classi di indirizzi) che
-direttamente come intero. In \file{netinet/in.h} vengono definiti anche alcune
-costanti per alcuni indirizzi speciali, che vedremo in
-\tabref{tab:TCPel_ipv4_addr}.
+direttamente come intero. In \file{netinet/in.h} vengono definite anche alcune
+costanti che identificano alcuni indirizzi speciali, riportati in
+\tabref{tab:TCP_ipv4_addr}.
 
 Infine occorre sottolineare che sia gli indirizzi che i numeri di porta devono
 essere specificati in quello che viene chiamato \textit{network order}, cioè
@@ -957,229 +957,6 @@ Il formato usato per gli indirizzi in formato di presentazione 
 \index{socket|)}
 
 
-\section{Un esempio di applicazione}
-\label{sec:sock_appplication}
-
-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, 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 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, 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.
-
-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]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \includecodesample{listati/FullRead.c}
-  \end{minipage} 
-  \normalsize
-  \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 R. W. Stevens in \cite{UNP1}, si sono
-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 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
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \includecodesample{listati/FullWrite.c}
-  \end{minipage} 
-  \normalsize
-  \caption{Funzione \func{FullWrite}, scrive \var{count} byte su un socket.}
-  \label{fig:sock_FullWrite_code}
-\end{figure}
-
-Come si può notare le funzioni ripetono la lettura/scrittura in un ciclo fino
-all'esaurimento del numero di byte richiesti, in caso di errore viene
-controllato se questo è \errcode{EINTR} (cioè un'interruzione della system call
-dovuta ad un segnale), nel qual caso l'accesso viene ripetuto, altrimenti
-l'errore viene ritornato interrompendo il ciclo.
-
-Nel caso della lettura, se il numero di byte letti è zero, significa che si è
-arrivati alla fine del file (per i socket questo significa in genere che
-l'altro capo è stato chiuso, e non è quindi più possibile leggere niente) e
-pertanto si ritorna senza aver concluso la lettura di tutti i byte richiesti.
-
-
-
-\subsection{Un primo esempio di client}
-\label{sec:net_cli_sample}
-
-Lo scopo di questo esempio è fornire un primo approccio alla programmazione di
-rete e vedere come si usano le funzioni descritte in precedenza, alcune delle
-funzioni usate nell'esempio saranno trattate in dettaglio nel capitolo
-successivo; qui ci limiteremo a introdurre la nomenclatura senza fornire
-definizioni precise e dettagli di funzionamento che saranno trattati
-estensivamente più avanti.
-
-In \figref{fig:net_cli_code} è riportata la sezione principale del codice del
-nostro client elementare per il servizio \textit{daytime}, un servizio
-standard che restituisce l'ora locale della macchina a cui si effettua la
-richiesta.
-
-\begin{figure}[!htb]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \includecodesample{listati/ElemDaytimeTCPClient.c}
-  \end{minipage} 
-  \normalsize
-  \caption{Esempio di codice di un client elementare per il servizio daytime.}
-  \label{fig:net_cli_code}
-\end{figure}
-
-Il sorgente completo del programma (\file{ElemDaytimeTCPClient.c}, che
-comprende il trattamento delle opzioni e una funzione per stampare un
-messaggio di aiuto) è allegato alla guida nella sezione dei codici sorgente e
-può essere compilato su una qualunque macchina Linux.
-
-Il programma anzitutto include gli header necessari (\texttt{\small 1--5});
-dopo la dichiarazione delle variabili (\texttt{\small 9--12}) si è omessa
-tutta la parte relativa al trattamento degli argomenti passati dalla linea di
-comando (effettuata con le apposite routine illustrate in
-\capref{sec:proc_opt_handling}).
-
-Il primo passo (\texttt{\small 14--18}) è creare un \textit{socket} IPv4
-(\const{AF\_INET}), di tipo TCP \const{SOCK\_STREAM}. La funzione
-\func{socket} ritorna il descrittore che viene usato per identificare il
-socket in tutte le chiamate successive. Nel caso la chiamata fallisca si
-stampa un errore con la relativa routine e si esce.
-
-Il passo seguente (\texttt{\small 19--27}) è quello di costruire un'apposita
-struttura \struct{sockaddr\_in} in cui sarà inserito l'indirizzo del server ed
-il numero della porta del servizio. Il primo passo è inizializzare tutto a
-zero, per poi inserire il tipo di protocollo e la porta (usando per
-quest'ultima la funzione \func{htons} per convertire il formato dell'intero
-usato dal computer a quello usato nella rete), infine si utilizza la funzione
-\func{inet\_pton} per convertire l'indirizzo numerico passato dalla linea di
-comando.
-
-Usando la funzione \func{connect} sul socket creato in precedenza
-(\texttt{\small 28--32}) si provvede poi a stabilire la connessione con il
-server specificato dall'indirizzo immesso nella struttura passata come secondo
-argomento, il terzo argomento è la dimensione di detta struttura. Dato che
-esistono diversi tipi di socket, si è dovuto effettuare un cast della
-struttura inizializzata in precedenza, che è specifica per i socket IPv4.  Un
-valore di ritorno negativo implica il fallimento della connessione.
-
-Completata con successo la connessione il passo successivo (\texttt{\small
-  34--40}) è leggere la data dal socket; il server invierà sempre una stringa
-di 26 caratteri della forma \verb|Wed Apr 4 00:53:00 2001\r\n|, che viene
-letta dalla funzione \func{read} e scritta su \file{stdout}.
-
-Dato il funzionamento di TCP la risposta potrà tornare in un unico pacchetto
-di 26 byte (come avverrà senz'altro nel caso in questione) ma potrebbe anche
-arrivare in 26 pacchetti di un byte.  Per questo nel caso generale non si può
-mai assumere che tutti i dati arrivino con una singola lettura, pertanto
-quest'ultima deve essere effettuata in un ciclo in cui si continui a leggere
-fintanto che la funzione \func{read} non ritorni uno zero (che significa che
-l'altro capo ha chiuso la connessione) o un numero minore di zero (che
-significa un errore nella connessione).
-
-Si noti come in questo caso la fine dei dati sia specificata dal server che
-chiude la connessione; questa è una delle tecniche possibili (è quella usata
-pure dal protocollo HTTP), ma ce ne possono essere altre, ad esempio FTP marca
-la conclusione di un blocco di dati con la sequenza ASCII \verb|\r\n|
-(carriage return e line feed), mentre il DNS mette la lunghezza in testa ad
-ogni blocco che trasmette. Il punto essenziale è che TCP non provvede nessuna
-indicazione che permetta di marcare dei blocchi di dati, per cui se questo è
-necessario deve provvedere il programma stesso.
-
-\subsection{Un primo esempio di server}
-\label{sec:net_serv_sample}
-
-Dopo aver illustrato il client daremo anche un esempio di un server
-elementare, in grado di rispondere al precedente client. Il listato è
-nuovamente mostrato in \figref{fig:net_serv_code}, il sorgente completo
-(\file{ElemDaytimeTCPServer.c}) è allegato insieme agli altri file nella
-directory \file{sources}.
-
-\begin{figure}[!htbp]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \includecodesample{listati/ElemDaytimeTCPServer.c}
-  \end{minipage} 
-  \normalsize
-  \caption{Esempio di codice di un semplice server per il servizio daytime.}
-  \label{fig:net_serv_code}
-\end{figure}
-
-Come per il client si includono gli header necessari a cui è aggiunto quello
-per trattare i tempi, e si definiscono alcune costanti e le variabili
-necessarie in seguito (\texttt{\small 1--18}), come nel caso precedente si
-sono omesse le parti relative al trattamento delle opzioni da riga di comando.
-
-La creazione del socket (\texttt{\small 22--26}) è analoga al caso precedente,
-come pure l'inizializzazione della struttura \struct{sockaddr\_in}, anche in
-questo caso si usa la porta standard del servizio daytime, ma come indirizzo
-IP si il valore predefinito \const{INET\_ANY} che corrisponde ad un indirizzo
-generico (\texttt{\small 27--31}).
-
-Si effettua poi (\texttt{\small 32--36}) la chiamata alla funzione
-\func{bind} che permette di associare la precedente struttura al socket, in
-modo che quest'ultimo possa essere usato per accettare connessioni su una
-qualunque delle interfacce di rete locali.
-
-Il passo successivo (\texttt{\small 37--41}) è mettere ``in ascolto'' il
-socket, questo viene effettuato con la funzione \func{listen} che dice al
-kernel di accettare connessioni per il socket specificato, la funzione indica
-inoltre, con il secondo parametro, il numero massimo di connessioni che il
-kernel accetterà di mettere in coda per il suddetto socket.
-
-Questa ultima chiamata completa la preparazione del socket per l'ascolto (che
-viene chiamato anche \textit{listening descriptor}) a questo punto il processo
-è mandato in sleep (\texttt{\small 44--47}) con la successiva chiamata alla
-funzione \func{accept}, fin quando non arriva e viene accettata una
-connessione da un client.
-
-Quando questo avviene \func{accept} ritorna un secondo descrittore di socket,
-che viene chiamato \textit{connected descriptor} che è quello che viene usato
-dalla successiva chiamata alla \func{write} per scrivere la risposta al
-client, una volta che si è opportunamente (\texttt{\small 48--49}) costruita
-la stringa con la data da trasmettere. Completata la trasmissione il nuovo
-socket viene chiuso (\texttt{\small 54}).  Il tutto è inserito in un ciclo
-infinito (\texttt{\small 42--55}) in modo da poter ripetere l'invio della data
-ad una successiva connessione.
-
-È importante notare che questo server è estremamente elementare, infatti a
-parte il fatto di essere dipendente da IPv4, esso è in grado di servire solo
-un client alla volta, è cioè un \textsl{server iterativo}, inoltre esso è
-scritto per essere lanciato da linea di comando, se lo si volesse utilizzare
-come demone di sistema occorrerebbero le opportune modifiche per tener conto
-di quanto illustrato in \secref{sec:sess_daemon}.
-
-
 
 %%% Local Variables: 
 %%% mode: latex