X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=elemtcp.tex;h=b074cb0fbb39a6712b371d3d2a440349284f9a26;hp=c57bbcf6f8aa0080bd5cb92878eb8c37b59242ba;hb=d47f15496fa85c8ec22edcde608f2665ec5b95ae;hpb=b324b7a09e071b2f84a1849d109d4d14f27f44cd;ds=sidebyside diff --git a/elemtcp.tex b/elemtcp.tex index c57bbcf..b074cb0 100644 --- a/elemtcp.tex +++ b/elemtcp.tex @@ -9,7 +9,7 @@ %% 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 @@ -1108,7 +1108,6 @@ scritti nella struttura puntata da \param{name}. Si tenga presente che se si 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 @@ -1146,7 +1145,8 @@ restituisce l'indirizzo remoto del socket, cio 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 @@ -1299,11 +1299,12 @@ nell'\href{http://www.ietf.org/rfc/rfc0867.txt}{RFC~867}, che restituisce 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 @@ -1350,9 +1351,10 @@ ritorna (\texttt{\small 31}). 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} @@ -1399,7 +1401,7 @@ elementare, che sia anche in grado di rispondere al precedente client. Come 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 @@ -1477,36 +1479,37 @@ non \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 @@ -1577,6 +1580,7 @@ torneremo su questo pi complessi. + \section{Un esempio più completo: il servizio \textit{echo}} \label{sec:TCP_echo_application} @@ -1587,54 +1591,58 @@ un po' pi 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 @@ -1647,27 +1655,28 @@ ricevuto in risposta dal server. \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 @@ -1705,7 +1714,7 @@ nel precedente esempio esaminato in \secref{sec:TCP_daytime_cunc_server}. 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