Correzione all'anno di Corpyright e alle pagine della home.
[gapil.git] / simpltcp.tex
index 8a6b2aed9a3a28077a8c3944748c741b36be9579..cd3dce8d21f953e8b9982dbcaabb31b758647561 100644 (file)
@@ -1,3 +1,13 @@
+%% simpltcp.tex
+%%
+%% Copyright (C) 2000-2002 Simone Piccardi.  Permission is granted to
+%% copy, distribute and/or modify this document under the terms of the GNU Free
+%% Documentation License, Version 1.1 or any later version published by the
+%% Free Software Foundation; with the Invariant Sections being "Prefazione",
+%% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
+%% license is included in the section entitled "GNU Free Documentation
+%% License".
+%%
 \chapter{Un esempio completo di client/server TCP}
 \label{cha:simple_TCP_sock}
 
 \chapter{Un esempio completo di client/server TCP}
 \label{cha:simple_TCP_sock}
 
@@ -51,61 +61,11 @@ parte, riportata in \figref{fig:TCPsimpl_serv_code}, 
 nel precedente esempio esaminato in \secref{sec:TCPel_cunc_serv}.
 
 \begin{figure}[!htb]
 nel precedente esempio esaminato in \secref{sec:TCPel_cunc_serv}.
 
 \begin{figure}[!htb]
-  \footnotesize
-  \begin{lstlisting}{}
-/* Subroutines declaration */
-void ServEcho(int sockfd);
-/* Program beginning */
-int main(int argc, char *argv[])
-{
-    int list_fd, conn_fd;
-    pid_t pid;
-    struct sockaddr_in serv_add;
-     ...
-    /* create socket */
-    if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-        perror("Socket creation error");
-        exit(-1);
-    }
-    /* initialize address */
-    memset((void *)&serv_add, 0, sizeof(serv_add)); /* clear server address */
-    serv_add.sin_family = AF_INET;                  /* address type is INET */
-    serv_add.sin_port = htons(13);                  /* daytime port is 13 */
-    serv_add.sin_addr.s_addr = htonl(INADDR_ANY);   /* connect from anywhere */
-    /* bind socket */
-    if (bind(list_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) {
-        perror("bind error");
-        exit(-1);
-    }
-    /* listen on socket */
-    if (listen(list_fd, BACKLOG) < 0 ) {
-        perror("listen error");
-        exit(-1);
-    }
-    /* handle echo to client */
-    while (1) {
-        /* accept connection */
-        if ( (conn_fd = accept(list_fd, NULL, NULL)) < 0) {
-            perror("accept error");
-            exit(-1);
-        }
-        /* fork to handle connection */
-        if ( (pid = fork()) < 0 ){
-            perror("fork error");
-            exit(-1);
-        }
-        if (pid == 0) {      /* child */
-            close(list_fd);          /* close listening socket */   
-            SockEcho(conn_fd);       /* handle echo */
-            exit(0);
-        } else {             /* parent */
-            close(conn_fd);          /* close connected socket */
-        }
-    }
-    /* normal exit, never reached */
-    exit(0);
-}
-  \end{lstlisting}
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/ElemEchoTCPServer.c}
+  \end{minipage} 
+  \normalsize
   \caption{Codice della funzione \code{main} della prima versione del server
     per il servizio \texttt{echo}.}
   \label{fig:TCPsimpl_serv_code}
   \caption{Codice della funzione \code{main} della prima versione del server
     per il servizio \texttt{echo}.}
   \label{fig:TCPsimpl_serv_code}
@@ -126,25 +86,17 @@ Il codice della funzione \code{ServEcho} 
 all'interno del ciclo (linee \texttt{\small 6--8}).  I dati inviati dal client
 vengono letti dal socket con una semplice \func{read} (che ritorna solo in
 presenza di dati in arrivo), la riscrittura viene invece gestita dalla
 all'interno del ciclo (linee \texttt{\small 6--8}).  I dati inviati dal client
 vengono letti dal socket con una semplice \func{read} (che ritorna solo in
 presenza di dati in arrivo), la riscrittura viene invece gestita dalla
-funzione \func{SockWrite} (descritta in \figref{fig:sock_SockWrite_code}) che
+funzione \func{FullWrite} (descritta in \figref{fig:sock_FullWrite_code}) che
 si incarica di tenere conto automaticamente della possibilità che non tutti i
 dati di cui è richiesta la scrittura vengano trasmessi con una singola
 \func{write}.
 
 \begin{figure}[!htb]
 si incarica di tenere conto automaticamente della possibilità che non tutti i
 dati di cui è richiesta la scrittura vengano trasmessi con una singola
 \func{write}.
 
 \begin{figure}[!htb]
-  \footnotesize
-  \begin{lstlisting}{}
-void ServEcho(int sockfd) {
-    char buffer[MAXLINE];
-    int nread, nwrite;
-    
-    /* main loop, reading 0 char means client close connection */
-    while ( (nread = read(sockfd, buffer, MAXLINE)) != 0) {
-        nwrite = SockWrite(sockfd, buffer, nread);
-    }
-    return;
-}
-  \end{lstlisting}
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/ServEcho.c}
+  \end{minipage} 
+  \normalsize
   \caption{Codice della prima versione della funzione \code{ServEcho} per la
     gestione del servizio \texttt{echo}.}
   \label{fig:TCPsimpl_server_elem_sub}
   \caption{Codice della prima versione della funzione \code{ServEcho} per la
     gestione del servizio \texttt{echo}.}
   \label{fig:TCPsimpl_server_elem_sub}
@@ -164,42 +116,13 @@ esso ricalca la struttura del precedente client per il servizio
 \texttt{daytime} (vedi \secref{sec:net_cli_sample}) ma, come per il server, lo
 si è diviso in due parti, inserendo la parte relativa alle operazioni
 specifiche previste per il protocollo \texttt{echo} in una funzione a parte.
 \texttt{daytime} (vedi \secref{sec:net_cli_sample}) ma, come per il server, lo
 si è diviso in due parti, inserendo la parte relativa alle operazioni
 specifiche previste per il protocollo \texttt{echo} in una funzione a parte.
+
 \begin{figure}[!htb]
 \begin{figure}[!htb]
-  \footnotesize
-  \begin{lstlisting}{}
-int main(int argc, char *argv[])
-{
-/* 
- * Variables definition  
- */
-    int sock_fd, i;
-    struct sockaddr_in serv_add;
-    ...
-    /* create socket */
-    if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-        perror("Socket creation error");
-        return -1;
-    }
-    /* initialize address */
-    memset((void *) &serv_add, 0, sizeof(serv_add)); /* clear server address */
-    serv_add.sin_family = AF_INET;                   /* address type is INET */
-    serv_add.sin_port = htons(7);                    /* echo port is 7 */
-    /* build address using inet_pton */
-    if ( (inet_pton(AF_INET, argv[optind], &serv_add.sin_addr)) <= 0) {
-        perror("Address creation error");
-        return -1;
-    }
-    /* extablish connection */
-    if (connect(sock_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) {
-        perror("Connection error");
-        return -1;
-    }
-    /* read daytime from server */
-    ClientEcho(stdin, sock_fd);
-    /* normal exit */
-    return 0;
-}
-  \end{lstlisting}
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6 cm}
+    \includecodesample{listati/EchoServerWrong.c}
+  \end{minipage} 
+  \normalsize
   \caption{Codice della prima versione del client \texttt{echo}.}
   \label{fig:TCPsimpl_client_elem}
 \end{figure}
   \caption{Codice della prima versione del client \texttt{echo}.}
   \label{fig:TCPsimpl_client_elem}
 \end{figure}
@@ -210,29 +133,18 @@ in \secref{sec:net_cli_sample}, 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).
 
 all'indirizzo specificato dalla linea di comando (a cui si è aggiunta una
 elementare gestione delle opzioni non riportata in figura).
 
-Completata la connessione, al ritrno fiììdi  \func{connect} è ritornata, 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.
+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.
 
 \begin{figure}[!htb]
 
 \begin{figure}[!htb]
-  \footnotesize
-  \begin{lstlisting}{}
-void ClientEcho(FILE * filein, int socket) 
-{
-    char sendbuff[MAXLINE], recvbuff[MAXLINE];
-    int nread; 
-    while (fgets(sendbuff, MAXLINE, filein) != NULL) {
-        SockWrite(socket, sendbuff, strlen(sendbuff)); 
-        nread = SockRead(socket, recvbuff, strlen(sendbuff));        
-        recvbuff[nread] = 0;
-        fputs(recvbuff, stdout);
-    }
-    return;
-}
-  \end{lstlisting}
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/ClientEcho.c}
+  \end{minipage} 
+  \normalsize
   \caption{Codice della prima versione della funzione \texttt{ClientEcho} per 
     la gestione del servizio \texttt{echo}.}
   \label{fig:TCPsimpl_client_echo_sub}
   \caption{Codice della prima versione della funzione \texttt{ClientEcho} per 
     la gestione del servizio \texttt{echo}.}
   \label{fig:TCPsimpl_client_echo_sub}
@@ -243,12 +155,12 @@ La funzione utilizza due buffer per gestire i dati inviati e letti sul socket
 (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
 (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
-\macro{MAXLINE} caratteri) e la salva sul buffer di invio, la funzione
-\func{SockWrite} (\texttt{\small 3}) scrive detti dati sul socket (gestendo
+\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}).
 
 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{SockRead} sul buffer di
+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}. 
 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}. 
@@ -397,41 +309,34 @@ quando affronteremo il comportamento in caso di conclusioni anomale:
 Tutto questo riguarda la connessione, c'è però da tenere conto dell'effetto
 del procedimento di chiusura del processo figlio nel server (si veda quanto
 esaminato in \secref{sec:proc_termination}). In questo caso avremo l'invio del
 Tutto questo riguarda la connessione, c'è però da tenere conto dell'effetto
 del procedimento di chiusura del processo figlio nel server (si veda quanto
 esaminato in \secref{sec:proc_termination}). In questo caso avremo l'invio del
-segnale \macro{SIGCHLD} al padre, ma dato che non si è installato un
-manipolatore e che l'azione predefinita per questo segnale è quella di essere
+segnale \const{SIGCHLD} al padre, ma dato che non si è installato un
+gestore e che l'azione predefinita per questo segnale è quella di essere
 ignorato, non avendo predisposto la ricezione dello stato di terminazione,
 ignorato, non avendo predisposto la ricezione dello stato di terminazione,
-otterremo che il processo figlio entrerà nello stato di zombie (si riveda
-quanto illustrato in \secref{sec:sig_sigchld}), come risulterà ripetendo il
-comando \cmd{ps}:
+otterremo che il processo figlio entrerà nello stato di zombie\index{zombie}
+(si riveda quanto illustrato in \secref{sec:sig_sigchld}), come risulterà
+ripetendo il comando \cmd{ps}:
 \begin{verbatim}
  2356 pts/0    S      0:00 ./echod
  2359 pts/0    Z      0:00 [echod <defunct>]
 \end{verbatim}
 
 \begin{verbatim}
  2356 pts/0    S      0:00 ./echod
  2359 pts/0    Z      0:00 [echod <defunct>]
 \end{verbatim}
 
-Poiché non è possibile lasciare processi zombie che pur inattivi occupano
-spazio nella tabella dei processi e a lungo andare saturerebbero le risorse
-del kernel, occorrerà ricevere opportunamente lo stato di terminazione del
-processo (si veda \secref{sec:proc_wait}), cosa che faremo utilizzando
-\macro{SIGCHLD} secondo quanto illustrato in \secref{sec:sig_sigchld}.
+Poiché non è possibile lasciare processi zombie\index{zombie} che pur inattivi
+occupano spazio nella tabella dei processi e a lungo andare saturerebbero le
+risorse del kernel, occorrerà ricevere opportunamente lo stato di terminazione
+del processo (si veda \secref{sec:proc_wait}), cosa che faremo utilizzando
+\const{SIGCHLD} secondo quanto illustrato in \secref{sec:sig_sigchld}.
 
 La prima modifica al nostro server è pertanto quella di inserire la gestione
 
 La prima modifica al nostro server è pertanto quella di inserire la gestione
-della terminazione dei processi figli attraverso l'uso di un manipolatore.
+della terminazione dei processi figli attraverso l'uso di un gestore.
 Per questo useremo la funzione \code{Signal}, illustrata in
 Per questo useremo la funzione \code{Signal}, illustrata in
-\figref{fig:sig_Signal_code}, per installare il semplice manipolatore che
+\figref{fig:sig_Signal_code}, per installare il semplice gestore che
 riceve i segnali dei processi figli terminati già visto in 
 \figref{fig:sig_sigchld_handl}; aggiungendo il seguente codice:
 riceve i segnali dei processi figli terminati già visto in 
 \figref{fig:sig_sigchld_handl}; aggiungendo il seguente codice:
-\begin{lstlisting}{}
-    ...
-    /* install SIGCHLD handler */
-    Signal(SIGCHLD, sigchld_hand);  /* establish handler */
-    /* create socket */
-    ...
-\end{lstlisting}
-
+\includecodesnip{listati/sigchildhand.c}
 \noindent
 all'esempio illustrato in \figref{fig:TCPsimpl_serv_code}, e linkando il tutto
 alla funzione \code{sigchld\_hand}, si risolverà completamente il problema
 \noindent
 all'esempio illustrato in \figref{fig:TCPsimpl_serv_code}, e linkando il tutto
 alla funzione \code{sigchld\_hand}, si risolverà completamente il problema
-degli zombie.
+degli zombie\index{zombie}.