La figura, era rimasta indietro
[gapil.git] / simpltcp.tex
index dab0667152882f122c87f82d7ce287189515377b..7d0291f9b66a353f25359857a0bdfe6d46e5a401 100644 (file)
@@ -58,64 +58,14 @@ 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
 parte, riportata in \figref{fig:TCPsimpl_serv_code}, è analoga a quella vista
 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
 parte, riportata in \figref{fig:TCPsimpl_serv_code}, è analoga a quella vista
-nel precedente esempio esaminato in \secref{sec:TCPel_cunc_serv}.
+nel precedente esempio esaminato in \secref{sec:TCP_cunc_daytime}.
 
 \begin{figure}[!htb]
 
 \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}
@@ -123,8 +73,8 @@ int main(int argc, char *argv[])
 
 La struttura di questa prima versione del server è sostanzialmente identica a
 quella dell'esempio citato, ed ad esso si applicano le considerazioni fatte in
 
 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:TCPel_cunc_daytime}. Le uniche differenze rispetto all'esempio in
-\figref{fig:TCPel_serv_code} sono che in questo caso per il socket in ascolto
+\secref{sec:TCP_cunc_daytime}. Le uniche differenze rispetto all'esempio in
+\figref{fig:TCP_serv_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
 viene usata la porta 7 e che tutta la gestione della comunicazione è delegata
 alla funzione \code{ServEcho}.
 %  Per ogni connessione viene creato un
@@ -136,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}
@@ -171,78 +113,38 @@ del processo figlio.
 
 Il codice del client è riportato in \figref{fig:TCPsimpl_client_elem}, anche
 esso ricalca la struttura del precedente client per il servizio
 
 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:net_cli_sample}) ma, come per il server, lo
+\texttt{daytime} (vedi \secref{sec:TCP_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.
 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}
 
 La funzione \code{main} si occupa della creazione del socket e della
 connessione (linee \texttt{\small 10--27}) secondo la stessa modalità spiegata
   \caption{Codice della prima versione del client \texttt{echo}.}
   \label{fig:TCPsimpl_client_elem}
 \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:net_cli_sample}, il client si connette sulla porta 7
+in \secref{sec:TCP_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}
@@ -253,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}. 
@@ -387,7 +289,7 @@ quando affronteremo il comportamento in caso di conclusioni anomale:
   server a cui questo risponderà con un ACK.  A questo punto il client verrà a
   trovarsi nello stato \texttt{FIN\_WAIT\_2} ed il server nello stato
   \texttt{CLOSE\_WAIT} (si riveda quanto spiegato in
   server a cui questo risponderà con un ACK.  A questo punto il client verrà a
   trovarsi nello stato \texttt{FIN\_WAIT\_2} ed il server nello stato
   \texttt{CLOSE\_WAIT} (si riveda quanto spiegato in
-  \secref{sec:TCPel_conn_term}).
+  \secref{sec:TCP_conn_term}).
 \item quando il server riceve il FIN la \func{read} del processo figlio che
   gestisce la connessione ritorna restituendo 0 causando così l'uscita dal
   ciclo e il ritorno di \code{ServEcho}, a questo punto il processo figlio
 \item quando il server riceve il FIN la \func{read} del processo figlio che
   gestisce la connessione ritorna restituendo 0 causando così l'uscita dal
   ciclo e il ritorno di \code{ServEcho}, a questo punto il processo figlio
@@ -407,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}.