%% License".
%%
\chapter{Socket TCP}
-\label{cha:elem_TCP_sock}
+\label{cha:TCP_socket}
In questo capitolo iniziamo ad approfondire la conoscenza dei socket TCP,
iniziando con una descrizione delle principali caratteristiche del
utilizzato un buffer troppo piccolo per \param{name} l'indirizzo risulterà
troncato.
-
La funzione si usa tutte le volte che si vuole avere l'indirizzo locale di un
socket; ad esempio può essere usata da un client (che usualmente non chiama
\func{bind}) per ottenere numero IP e porta locale associati al socket
capo della connessione. Ci si può chiedere a cosa serva questa funzione dato
che dal lato client l'indirizzo remoto è sempre noto quando si esegue la
\func{connect} mentre dal lato server si possono usare, come vedremo in
-\figref{fig:TCP_cunc_serv_code}, i valori di ritorno di \func{accept}.
+\figref{fig:TCP_daytime_cunc_server_code}, i valori di ritorno di
+\func{accept}.
Il fatto è che in generale quest'ultimo caso non è sempre possibile. In
particolare questo avviene quando il server, invece di gestire la connessione
l'ora locale della macchina a cui si effettua la richiesta, e che è assegnato
alla porta 13.
-In \figref{fig:TCP_cli_code} è riportata la sezione principale del codice del
-nostro client. Il sorgente completo del programma (\file{TCP_daytime.c}, che
-comprende il trattamento delle opzioni ed una funzione per stampare un
-messaggio di aiuto) è allegato alla guida nella sezione dei codici sorgente e
-può essere compilato su una qualunque macchina GNU/Linux.
+In \figref{fig:TCP_daytime_client_code} è riportata la sezione principale del
+codice del nostro client. Il sorgente completo del programma
+(\file{TCP\_daytime.c}, che comprende il trattamento delle opzioni ed una
+funzione per stampare un messaggio di aiuto) è allegato alla guida nella
+sezione dei codici sorgente e può essere compilato su una qualunque macchina
+GNU/Linux.
\begin{figure}[!htb]
\footnotesize \centering
Completata con successo la connessione il passo successivo (\texttt{\small
34--40}) è leggere la data dal socket; il protocollo prevede che il server
-invii sempre una stringa alfanumerica di 26 caratteri, nella forma giorno
-della settimana, mese, ora minuto e secondo, anno, seguita dai caratteri di
-terminazione \verb|\r\n|, cioè qualcosa del tipo:
+invii sempre una stringa alfanumerica, il formato della stringa non è
+specificato dallo standard, per cui noi useremo il formato usato dalla
+funzione \func{ctime}, seguito dai caratteri di terminazione \verb|\r\n|, cioè
+qualcosa del tipo:
\begin{verbatim}
Wed Apr 4 00:53:00 2001\r\n
\end{verbatim}
primo esempio realizzeremo un server iterativo, in grado di fornire una sola
risposta alla volta. Il codice del programma è nuovamente mostrato in
\figref{fig:TCP_daytime_iter_server_code}, il sorgente completo
-(\file{TCP_iter_daytimed.c}) è allegato insieme agli altri file degli esempi.
+(\file{TCP\_iter\_daytimed.c}) è allegato insieme agli altri file degli esempi.
\begin{figure}[!htbp]
\footnotesize \centering
\subsection{Un server \textit{daytime} concorrente}
\label{sec:TCP_daytime_cunc_server}
-Il server \texttt{daytime} dell'esempio in \secref{sec:TCP_daytime_client} è un
-tipico esempio di server iterativo, in cui viene servita una richiesta alla
-volta; in generale però, specie se il servizio è più complesso e comporta uno
-scambio di dati più sostanzioso di quello in questione, non è opportuno
-bloccare un server nel servizio di un client per volta; per questo si ricorre
-alle capacità di multitasking del sistema.
+Il server \texttt{daytime} dell'esempio in
+\secref{sec:TCP_daytime_iter_server} è un tipico esempio di server iterativo,
+in cui viene servita una richiesta alla volta; in generale però, specie se il
+servizio è più complesso e comporta uno scambio di dati più sostanzioso di
+quello in questione, non è opportuno bloccare un server nel servizio di un
+client per volta; per questo si ricorre alle capacità di multitasking del
+sistema.
Come accennato anche in \secref{sec:proc_gen} una delle modalità più comuni di
funzionamento da parte dei server è quella di usare la funzione \func{fork}
per creare, ad ogni richiesta da parte di un client, un processo figlio che si
incarichi della gestione della comunicazione. Si è allora riscritto il server
-\texttt{daytime} dell'esempio precedente in forma concorrente, inserendo anche
+\textit{daytime} dell'esempio precedente in forma concorrente, inserendo anche
una opzione per la stampa degli indirizzi delle connessioni ricevute.
-In \figref{fig:TCP_cunc_serv_code} è mostrato un estratto del codice, in cui
-si sono tralasciati il trattamento delle opzioni e le parti rimaste invariate
-rispetto al precedente esempio (cioè tutta la parte riguardante l'apertura
-passiva del socket). Al solito il sorgente completo del server, nel file
-\file{ElemDaytimeTCPCuncServ.c}, è allegato insieme ai sorgenti degli altri
-esempi.
+In \figref{fig:TCP_daytime_cunc_server_code} è mostrato un estratto del
+codice, in cui si sono tralasciati il trattamento delle opzioni e le parti
+rimaste invariate rispetto al precedente esempio (cioè tutta la parte
+riguardante l'apertura passiva del socket). Al solito il sorgente completo del
+server, nel file \file{TCP\_cunc\_daytimed.c}, è allegato insieme ai sorgenti
+degli altri esempi.
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \includecodesample{listati/ElemDaytimeTCPCuncServ.c}
+ \includecodesample{listati/TCP_cunc_daytimed.c}
\end{minipage}
\normalsize
\caption{Esempio di codice di un server concorrente elementare per il
servizio daytime.}
- \label{fig:TCP_cunc_serv_code}
+ \label{fig:TCP_daytime_cunc_server_code}
\end{figure}
Stavolta (\texttt{\small 21--25}) la funzione \func{accept} è chiamata
complessi.
+
\section{Un esempio più completo: il servizio \textit{echo}}
\label{sec:TCP_echo_application}
le direzioni, implementando il servizio standard \textit{echo}, così come
definito dall'\href{http://www.ietf.org/rfc/rfc0862.txt}{RFC~862}.
-Si è scelto di usare questo servizio, seguendo l'esempio di \cite{UNP1},
-perché costituisce il prototipo ideale di una generica applicazione di rete in
-cui un server risponde alle richieste di un client; nel caso di una
-applicazione più complessa si potrà avere in più una elaborazione dell'input
-del client da parte del server nel fornire le risposte in uscita.
+Si è scelto, seguendo l'esempio di \cite{UNP1}, di usare questo servizio, che
+si limita a restituire in uscita quanto immesso in ingresso, perché nonostante
+la sua estrema semplicità costituisce il prototipo ideale di una generica
+applicazione di rete in cui un server risponde alle richieste di un client;
+nel caso di una applicazione più complessa si potrà avere in più una
+elaborazione dell'input del client da parte del server nel fornire le risposte
+in uscita.
-Ci limiteremo ad un esempio elementare, che usi solo le funzioni di base, ma
-prenderemo in esame, oltre al comportamento in condizioni normali, anche tutti
-i possibili scenari particolari (errori, sconnessione della rete, crash del
-client o del server durante la connessione) che possono avere luogo durante
-l'impiego di un'applicazione di rete.
+Ci limiteremo per ora ad una implementazione elementare, che usi solo le
+funzioni di base, ma prenderemo in esame, oltre al comportamento in condizioni
+normali, anche tutti i possibili scenari particolari (errori, sconnessione
+della rete, crash del client o del server durante la connessione) che possono
+avere luogo durante l'impiego di un'applicazione di rete, partendo da una
+versione primitiva che dovrà essere rimaneggiata di volta in volta per poter
+tenere conto di tutte le evenienze che si possono manifestare nella vita reale
+di un'applicazione di rete, fino ad arrivare ad un'implementazione completa.
-Partiremo da un'implementazione elementare che dovrà essere rimaneggiata di
-volta in volta per poter tenere conto di tutte le evenienze che si possono
-manifestare nella vita reale di un'applicazione di rete, fino ad arrivare ad
-un'implementazione completa.
\subsection{Il client: prima versione}
\label{sec:TCP_echo_client}
-Il codice del client è riportato in \figref{fig:TCPsimpl_client_elem}, anche
-esso ricalca la struttura del precedente client per il servizio
-\texttt{daytime} (vedi \secref{sec:TCP_daytime_client}) ma, come per il
-server, lo si è diviso in due parti, inserendo la parte relativa alle
-operazioni specifiche previste per il protocollo \textit{echo} in una funzione
-a parte.
+Il codice della prima versione client per il servizio \textit{echo} è
+riportato in \figref{fig:TCP_echo_client_1}. Esso ricalca la struttura del
+precedente client per il servizio \textit{daytime} (vedi
+\secref{sec:TCP_daytime_client}), e la prima parte (\texttt{\small 10--27}) è
+sostanzialmente identica, a parte l'uso di una porta diversa.
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15.6 cm}
- \includecodesample{listati/EchoServerWrong.c}
+ \includecodesample{listati/TCP_echo_client.c}
\end{minipage}
\normalsize
\caption{Codice della prima versione del client \textit{echo}.}
- \label{fig:TCPsimpl_client_elem}
+ \label{fig:TCP_echo_client_1}
\end{figure}
-La funzione \code{main} si occupa della creazione del socket e della
-connessione (linee \texttt{\small 10--27}) secondo la stessa modalità spiegata
-in \secref{sec:TCP_daytime_client}, il client si connette sulla porta 7
-all'indirizzo specificato dalla linea di comando (a cui si è aggiunta una
-elementare gestione delle opzioni non riportata in figura).
-
-Completata la connessione, al ritorno di \func{connect}, la funzione
-\code{ClientEcho}, riportata in \figref{fig:TCPsimpl_client_echo_sub}, si
-preoccupa di gestire la comunicazione, leggendo una riga alla volta dallo
-\file{stdin}, scrivendola sul socket e ristampando su \file{stdout} quanto
-ricevuto in risposta dal server.
+Al solito si è tralasciata la sezione relativa alla gestione delle opzioni a
+riga di comando; una volta dichiarate le variabili, si prosegue
+(\texttt{\small 10--13}) con della creazione del socket, la preparazione
+(\texttt{\small 14--17}) la struttura per l'indirizzo, con la relativa
+conversione (\texttt{\small 18--22}) di quanto specificato a riga di comando.
+
+A questo punto (\texttt{\small 23--27}) si può eseguire la connessione al
+server secondo la stessa modalità usata in \secref{sec:TCP_daytime_client}.
+Completata la connessione, al ritorno di \func{connect}, si usa la funzione
+\code{ClientEcho}, il cui codice è riportato in
+\figref{fig:TCPsimpl_client_echo_sub}. Questa si preoccupa di gestire tutta la
+comunicazione, leggendo una riga alla volta dallo standard input \file{stdin},
+scrivendola sul socket e ristampando su \file{stdout} quanto ricevuto in
+risposta dal server. Al ritorno dalla funzione (\texttt{\small 30--31}) anche
+il programma termina.
\begin{figure}[!htb]
\footnotesize \centering
\label{fig:TCPsimpl_client_echo_sub}
\end{figure}
-La funzione utilizza due buffer per gestire i dati inviati e letti sul socket
-(\texttt{\small 3}). La comunicazione viene gestita all'interno di un ciclo
-(linee \texttt{\small 5--10}), i dati da inviare sulla connessione vengono
-presi dallo \file{stdin} usando la funzione \func{fgets} che legge una
-linea di testo (terminata da un \texttt{CR} e fino al massimo di
-\const{MAXLINE} caratteri) e la salva sul buffer di invio, la funzione
-\func{FullWrite} (\texttt{\small 3}) scrive detti dati sul socket (gestendo
-l'invio multiplo qualora una singola \func{write} non basti, come spiegato
-in \secref{sec:sock_io_behav}).
+La funzione \code{ClientEcho} utilizza due buffer (\texttt{\small 3}) per
+gestire i dati inviati e letti sul socket. La comunicazione viene gestita
+all'interno di un ciclo (\texttt{\small 5--10}), i dati da inviare sulla
+connessione vengono presi dallo \file{stdin} usando la funzione \func{fgets},
+trattata in \secref{sec:file_line_io}, che legge una linea di testo (terminata
+da un \texttt{CR} e fino al massimo di \const{MAXLINE} caratteri) e la salva
+sul buffer di invio, la funzione \func{FullWrite}, già vista in
+\figref{fig:sock_FullWrite_code}, scrive (\texttt{\small 6}) i dati sul socket
+(gestendo l'invio multiplo qualora una singola \func{write} non basti, come
+spiegato in \secref{sec:sock_io_behav}).
-I dati che vengono riletti indietro con una \func{FullRead} sul buffer di
-ricezione e viene inserita la terminazione della stringa (\texttt{\small
- 7--8}) e per poter usare la funzione \func{fputs} per scriverli su
-\file{stdout}.
+I dati vengono riletti indietro (\texttt{\small 7}) con una \func{FullRead}
+sul buffer di ricezione e viene inserita (\texttt{\small 8}) la terminazione
+della stringa e per poter usare (\texttt{\small 9}) la funzione \func{fputs}
+per scriverli su \file{stdout}.
-Un end of file inviato su \file{stdin} causa il ritorno di \func{fgets}
-con un puntatore nullo e l'uscita dal ciclo, al che la subroutine ritorna ed
-il client esce.
+Un end-of-file inviato su \file{stdin} (ad esempio con la pressione di
+\texttt{C-d}) causa il ritorno di \func{fgets} con un puntatore nullo e la
+conseguente uscita dal ciclo, al che la subroutine ritorna ed il client esce.
-\subsection{La struttura del server}
+\subsection{Il server: prima versione}
\label{sec:TCPsimp_server_main}
Il servizio \textit{echo} è uno dei servizi standard solitamente provvisti
La struttura di questa prima versione del server è sostanzialmente identica a
quella dell'esempio citato, ed ad esso si applicano le considerazioni fatte in
\secref{sec:TCP_daytime_cunc_server}. Le uniche differenze rispetto
-all'esempio in \figref{fig:TCP_daytime_iter_server_code} sono che in questo
+all'esempio in \figref{fig:TCP_daytime_cunc_server_code} sono che in questo
caso per il socket in ascolto viene usata la porta 7 e che tutta la gestione
della comunicazione è delegata alla funzione \code{ServEcho}.
% Per ogni connessione viene creato un