Modifiche varie per i test delle situazioni limite
authorSimone Piccardi <piccardi@gnulinux.it>
Sun, 27 Jul 2003 14:28:19 +0000 (14:28 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sun, 27 Jul 2003 14:28:19 +0000 (14:28 +0000)
elemtcp.tex
intro.tex
sources/ErrCode.c
sources/TCP_echo.c
sources/TCP_echod.c

index 70caf59463babdf922a02ac50eeca7eb94622cbe..1ae67f4a24b6bc29b1806b2b3e737b08ac5c01dc 100644 (file)
@@ -1053,12 +1053,12 @@ errori rispetto ad altre implementazioni dei socket BSD, infatti la funzione
 \func{accept} passa gli errori di rete pendenti sul nuovo socket come codici
 di errore per \func{accept}, per cui l'applicazione deve tenerne conto ed
 eventualmente ripetere la chiamata alla funzione come per l'errore di
-\errcode{EAGAIN}. Un'altra differenza con BSD è che la funzione non fa
-ereditare al nuovo socket i flag del socket originale, come
-\const{O\_NONBLOCK},\footnote{ed in generale tutti quelli che si possono
-  impostare con \func{fcntl}, vedi \secref{sec:file_fcntl}.} che devono essere
-rispecificati ogni volta. Tutto questo deve essere tenuto in conto se si
-devono scrivere programmi portabili.
+\errcode{EAGAIN} (torneremo su questo in \secref{sec:TCP_echo_critical}).
+Un'altra differenza con BSD è che la funzione non fa ereditare al nuovo socket
+i flag del socket originale, come \const{O\_NONBLOCK},\footnote{ed in generale
+  tutti quelli che si possono impostare con \func{fcntl}, vedi
+  \secref{sec:file_fcntl}.} che devono essere rispecificati ogni volta. Tutto
+questo deve essere tenuto in conto se si devono scrivere programmi portabili.
 
 Il meccanismo di funzionamento di \func{accept} è essenziale per capire il
 funzionamento di un server: in generale infatti c'è sempre un solo socket in
@@ -2078,8 +2078,9 @@ modificata per la seconda versione del programma.
     \includecodesample{listati/TCP_echod.c}
   \end{minipage} 
   \normalsize
-  \caption{Sezione del codice seconda versione del server
-    per il servizio \textit{echo} modificate rispetto alla prima.}
+  \caption{La sezione nel codice della seconda versione del server
+    per il servizio \textit{echo} modificata per tener conto dell'interruzione
+    delle system call.}
   \label{fig:TCP_echo_server_code}
 \end{figure}
 
@@ -2122,19 +2123,24 @@ la rete 
 gestire tutta una serie di situazioni critiche che non esistono per i processi
 locali.
 
+
+\subsection{La terminazione precoce della connessione}
+\label{sec:TCP_conn_early_abort}
+
 La prima situazione critica è quella della terminazione precoce, causata da un
 qualche errore sulla rete, della connessione effettuata da un client. Come
 accennato in \secref{sec:TCP_func_accept} la funzione \func{accept} riporta
 tutti gli eventuali errori di rete pendenti su una connessione sul
 \textit{connected socket}. Di norma questo non è un problema, in quanto non
 appena completata la connessione, \func{accept} ritorna e l'errore sarà
-rilevato in seguito dal processo che gestisce la connessione alla prima
-chiamata di una funzione che opera sul socket..
+rilevato in seguito, dal processo che gestisce la connessione, alla prima
+chiamata di una funzione che opera sul socket.
 
 È però possibile, dal punto di vista teorico, incorrere anche in uno scenario
 del tipo di quello mostrato in \figref{fig:TCP_early_abort}, in cui la
-connessione viene abortita sul lato client con l'invio di un segmento RST,
-prima che nel server sia stata chiamata la funzione \func{accept}.
+connessione viene abortita sul lato client per un qualche errore di rete con
+l'invio di un segmento RST, prima che nel server sia stata chiamata la
+funzione \func{accept}.
 
 \begin{figure}[htb]
   \centering
@@ -2148,8 +2154,8 @@ con dei server molto occupati. In tal caso, con una struttura del server
 simile a quella del nostro esempio, in cui la gestione delle singole
 connessioni è demandata a processi figli, può accadere che il three way
 handshake venga completato e la relativa connessione abortita subito dopo,
-prima che il padre, per via del carico della macchina, abbia fatto in tempo a
-rieseguire la chiamata ad \func{accept}. Di nuovo si ha una situazione analoga
+prima che il padre, per via del carico della macchina, abbia fatto in tempo ad
+eseguire la chiamata ad \func{accept}. Di nuovo si ha una situazione analoga
 a quella illustrata in \figref{fig:TCP_early_abort}, in cui la connessione
 viene stabilita, ma subito dopo si ha una condizione di errore che la chiude
 prima che essa sia stata accettata dal programma.
@@ -2160,17 +2166,34 @@ abbiamo trattato in \secref{sec:TCP_child_hand} nel caso particolare di
 \func{accept}, che come nel caso precedente, necessitano semplicemente la
 ripetizione della chiamata senza che si debba uscire dal programma. In questo
 caso anche la versione modificata del nostro server non sarebbe adatta, in
-quanto uno di questi errori causerebbe la terminazione dello stesso.
+quanto uno di questi errori causerebbe la terminazione dello stesso. In Linux
+i possibili errori di rete non fatali, riportati sul socket connesso al
+ritorno di \func{accept}, sono \errcode{ENETDOWN}, \errcode{EPROTO},
+\errcode{ENOPROTOOPT}, \errcode{EHOSTDOWN}, \errcode{ENONET},
+\errcode{EHOSTUNREACH}, \errcode{EOPNOTSUPP} e \errcode{ENETUNREACH}.
 
 Si tenga presente che questo tipo di terminazione non è riproducibile
 terminando il client prima della chiamata ad \func{accept}; in tal caso
 infatti il socket associato alla connessione viene semplicemente chiuso,
 attraverso la sequenza vista in \secref{sec:TCP_conn_term}, per cui la
 \func{accept} ritornerà senza errori, e si avrà semplicemente un end-of-file
-al primo accesso al socket. Per riprodurre l'errore occorrerebbe usare
-l'opzione \const{SO\_LINGER} (vedi \secref{sec:xxx}) per chiedere al client di
-chiudere il socket con un segmento RST, invece che con la normale sequenza di
-chiusura.
+al primo accesso al socket. Nel caso di Linux inoltre anche l'invio da parte
+del client di un segmento di RST non provoca nessun errore al ritorno di
+\funcd{accept} quanto un errore di \errcode{ECONNRESET} al primo tentativo di
+accesso al socket.
+
+
+
+\subsection{Il crollo del server}
+\label{sec:TCP_server_crash}
+
+Un secondo caso critico è quello in cui si ha il crollo del server. In tal
+caso si suppone che il processo del server termini per un errore fatale, cosa
+che potremo simulare inviandogli un segnale di terminazione. La conclusione
+del processo comporta la chiusura di tutti i file aperti, compresi tutti i
+socket relativi a connessioni stabilite; questo significa che al momento del
+crollo del servizio il client riceverà un FIN dal server in corrispondenza
+della chiusura del socket.
 
 
 
index 1ca91b41ab7782f45cae4c640f70912c8ef0af2a..89eb59c664d3702e7a0402a9c44e59f757d40878 100644 (file)
--- a/intro.tex
+++ b/intro.tex
@@ -701,10 +701,10 @@ esplicitamente definendo la macro \macro{\_GNU\_SOURCE} prima di
 includere i vari header file.
 
 
-\subsection{Gli standard di GNU/Linux}
-\label{sec:intro_linux_std}
+%% \subsection{Gli standard di GNU/Linux}
+%% \label{sec:intro_linux_std}
 
-Da fare (o cassare, a seconda del tempo e della voglia).
+%% Da fare (o cassare, a seconda del tempo e della voglia).
 
 
 
index 7fc5ab86d501e95a4953b7fbf5035b5f6e6d2c02..d8b6906bfeec6ae00d129f75859f69065b4b8f09 100644 (file)
@@ -26,7 +26,7 @@
  *
  * Usage: errcode -h give all info's
  *
- * $Id: ErrCode.c,v 1.7 2003/05/02 09:55:13 piccardi Exp $ 
+ * $Id: ErrCode.c,v 1.8 2003/07/27 14:28:19 piccardi Exp $ 
  *
  ****************************************************************/
 /* 
@@ -247,7 +247,7 @@ int main(int argc, char *argv[])
 void usage(void) {
     printf("Print error code message or macro label \n");
     printf("Usage:\n");
-    printf("  daytime [-h] [-l] [-m] error code \n");
+    printf("  errcode [-h] [-l] [-m] error code \n");
     printf("  -m          print error messages\n");
     printf("  -l          print error code label\n");
     printf("  -h          print this help\n");
index 2a6f921dd54a2543b75bc09b01e2f5ac30532632..48e0326a20fb4e84ab440f5f36071ceda0d5f8c4 100644 (file)
@@ -26,7 +26,7 @@
  *
  * Usage: echo -h give all info's
  *
- * $Id: TCP_echo.c,v 1.2 2003/06/23 18:48:04 piccardi Exp $
+ * $Id: TCP_echo.c,v 1.3 2003/07/27 14:28:19 piccardi Exp $
  *
  ****************************************************************/
 /* 
@@ -37,6 +37,8 @@
 #include <arpa/inet.h>   /* IP addresses conversion utiliites */
 #include <sys/socket.h>  /* socket library */
 #include <stdio.h>      /* include standard I/O library */
+#include <errno.h>      /* include error codes */
+#include <string.h>     /* include erroro strings definitions */
 
 #define MAXLINE 256
 void usage(void);
@@ -113,6 +115,7 @@ int main(int argc, char *argv[])
            perror("Cannot set linger");
            exit(1);
        }
+       return 0;
     }
     /* read daytime from server */
     ClientEcho(stdin, sock);
@@ -135,12 +138,20 @@ void usage(void) {
 void ClientEcho(FILE * filein, int socket) 
 {
     char sendbuff[MAXLINE+1], recvbuff[MAXLINE+1];
-    int nread; 
+    int nread, nwrite
     while (fgets(sendbuff, MAXLINE, filein) != NULL) {
-       FullWrite(socket, sendbuff, strlen(sendbuff)); 
+       nwrite = FullWrite(socket, sendbuff, strlen(sendbuff)); 
+       if (nwrite < 0) {
+           printf("Errore in scrittura %s", strerror(errno));
+       }
        nread = FullRead(socket, recvbuff, strlen(sendbuff));
+       if (nread < 0) {
+           printf("Errore in lettura %s", strerror(errno));
+       }
        recvbuff[nread] = 0;
-       fputs(recvbuff, stdout);
+       if (fputs(recvbuff, stdout) == EOF) {
+           perror("Errore in scrittura su terminale");
+       }
     }
     return;
 }
index 576c47f2069ac3d03bcd2b177af409d20f9c9bdb..049155744c919942c335a3a5f3b818ce0005990f 100644 (file)
@@ -26,7 +26,7 @@
  *
  * Usage: echod -h give all info
  *
- * $Id: TCP_echod.c,v 1.7 2003/06/19 14:18:27 piccardi Exp $ 
+ * $Id: TCP_echod.c,v 1.8 2003/07/27 14:28:19 piccardi Exp $ 
  *
  ****************************************************************/
 /* 
@@ -41,6 +41,7 @@
 #include <syslog.h>      /* syslog system functions */
 #include <signal.h>      /* signal functions */
 #include <errno.h>       /* error code */
+#include <string.h>      /* error code */
 #include "Gapil.h"
 
 #define BACKLOG 10
@@ -198,7 +199,25 @@ void ServEcho(int sockfd) {
     int size;
     /* main loop, reading 0 char means client close connection */
     while ( (nread = read(sockfd, buffer, MAXLINE)) != 0) {
+       if (nread < 0) {
+           snprintf(debug, MAXLINE+20, "Errore in lettura: %s \n", 
+                    strerror(errno));
+           if (demonize) {          /* daemon mode */
+               syslog(LOG_DEBUG, debug);
+           } else {
+               printf("%s", debug);
+           }
+       }
        nwrite = FullWrite(sockfd, buffer, nread);
+       if (nwrite < 0) {
+           snprintf(debug, MAXLINE+20, "Errore in scrittura: %s \n", 
+                    strerror(errno));
+           if (demonize) {          /* daemon mode */
+               syslog(LOG_DEBUG, debug);
+           } else {
+               printf("%s", debug);
+           }       
+       }
        if (debugging) {
            buffer[nread] = 0;
            snprintf(debug, MAXLINE+20, "Letti %d byte, %s", nread, buffer);