From: Simone Piccardi Date: Tue, 29 Apr 2003 22:53:03 +0000 (+0000) Subject: Altre correzioni. X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=e3e15ed6d698e5cc35f3b7f4c5db96adc38255c3;p=gapil.git Altre correzioni. --- diff --git a/elemtcp.tex b/elemtcp.tex index b074cb0..b021a78 100644 --- a/elemtcp.tex +++ b/elemtcp.tex @@ -1588,33 +1588,56 @@ L'esempio precedente, basato sul servizio \textit{daytime}, elementare, in cui il flusso dei dati va solo nella direzione dal server al client. In questa sezione esamineremo un esempio di applicazione client/server un po' più complessa, che usi i socket TCP per una comunicazione in entrambe -le direzioni, implementando il servizio standard \textit{echo}, così come -definito dall'\href{http://www.ietf.org/rfc/rfc0862.txt}{RFC~862}. - -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 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. +le direzioni. + +Ci limiteremo a fornire una implementazione elementare, che usi solo le +funzioni di base viste finore, 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. + + +\subsection{Il servizio \textit{echo}} +\label{sec:TCP_echo} + + +Nella ricerca di un servizio che potesse fare da esempio per una comunicazione +bidirezionale, si è deciso, seguendo la scelta di Stevens in \cite{UNP1}, di +usare il servizio \textit{echo}, che si limita a restituire in uscita quanto +immesso in ingresso. Infatti, nonostante la sua estrema semplicità, questo +servizio costituisce il prototipo ideale per una generica applicazione di rete +in cui un server risponde alle richieste di un client. Nel caso di una +applicazione più complessa quello che si potrà avere in più è una elaborazione +dell'input del client, che in molti casi viene interpretato come un comando, +da parte di un server che risponde fornendo altri dati in uscita. + +Il servizio \textit{echo} è uno dei servizi standard solitamente provvisti +direttamente dal superserver \cmd{inetd}, ed è definito +dall'\href{http://www.ietf.org/rfc/rfc0862.txt}{RFC~862}. Come dice il nome il +servizio deve rimandare indietro sulla connessione i dati che gli vengono +inviati; l'RFC descrive le specifiche sia per TCP che UDP, e per il primo +stabilisce che una volta stabilita la connessione ogni dato in ingresso deve +essere rimandato in uscita, fintanto che il chiamante non ha chiude la +connessione; il servizio opera sulla porta 7. + +Nel nostro caso l'esempio sarà costituito da un client che legge una linea di +caratteri dallo standard input e la scrive sul server. A sua volta il server +leggerà la linea dalla connessione e la riscriverà immutata all'indietro. Sarà +compito del client leggere la risposta del server e stamparla sullo standard +output. \subsection{Il client: prima versione} \label{sec:TCP_echo_client} -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 +Il codice della prima versione client per il servizio \textit{echo}, +diponibile nel file \file{TCP_echo1.c}, è 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. @@ -1630,19 +1653,36 @@ sostanzialmente identica, a parte l'uso di una porta diversa. 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. +(\texttt{\small 10--13}) con della creazione del socket, con l'usuale +controllo degli errori, la preparazione (\texttt{\small 14--17}) della +struttura dell'indirizzo, che usa la porta 7 riservata al servizio +\textit{echo}, l'indirizzo specificato a riga di comando appositamente +convertito (\texttt{\small 18--22}). Una volta inizializzato l'indirizzo si si +può eseguire (\texttt{\small 23--27}) la connessione al server secondo la +stessa modalità usata in \secref{sec:TCP_daytime_client}. + +Completata la connessione, al ritorno di \func{connect}, per gestire il +funzionamento del protocollo si usa la funzione \code{ClientEcho}, il cui +codice si è riportato a parte 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. + +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}, +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. + +Si usa poi (\texttt{\small 6}) la funzione \func{FullWrite}, vista in +\secref{sec:sock_io_behav}, per scrivere i dati sul socket, gestendo +automaticamente l'invio multiplo qualora una singola \func{write} non sia +sufficiente. 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}. \begin{figure}[!htb] \footnotesize \centering @@ -1655,45 +1695,17 @@ il programma termina. \label{fig:TCPsimpl_client_echo_sub} \end{figure} -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 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} (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. +Quando si conluderà l'invio di dati mandando un end-of-file sullo standard +inputo (ad esempio con la pressione di \texttt{C-d}) si avrà il ritorno di +\func{fgets} con un puntatore nullo (si riveda quanto spiegato in +\secref{sec:file_line_io}) e la conseguente uscita dal ciclo; al che la +subroutine ritorna ed il nostro programma client termina. \subsection{Il server: prima versione} \label{sec:TCPsimp_server_main} -Il servizio \textit{echo} è uno dei servizi standard solitamente provvisti -direttamente dal superserver \cmd{inetd}, ed è definito -dall'\href{http://www.ietf.org/rfc/rfc0862.txt}{RFC~862}. Come dice il nome il -servizio deve rimandare indietro sulla connessione i dati che gli vengono -inviati; l'RFC descrive le specifiche sia per TCP che UDP, e per il primo -stabilisce che una volta stabilita la connessione ogni dato in ingresso deve -essere rimandato in uscita, fintanto che il chiamante non ha chiude la -connessione; il servizio opera sulla porta 7. - -Nel nostro caso l'esempio sarà costituito da un client che legge una linea di -caratteri dallo standard input e la scrive sul server, il server leggerà la -linea dalla connessione e la riscriverà all'indietro; sarà compito del client -leggere la risposta del server e stamparla sullo standard output. - -La prima versione del server, \file{ElemEchoTCPServer.c}, si compone di un +La prima versione del server, \file{TCP_echod.c}, si compone di un corpo principale, costituito dalla funzione \code{main}. Questa si incarica di creare il socket, metterlo in ascolto di connessioni in arrivo e creare un processo figlio a cui delegare la gestione di ciascuna connessione. Questa