Rinominato la prima versione del server.
[gapil.git] / elemtcp.tex
index 534dd398f18819943c1811ed5bbb63fcf5d556ab..90fcfb942272ba3a92f8f4cb2fbc8b5dba8a8391 100644 (file)
@@ -1711,23 +1711,23 @@ illustriamo immediatamente.
 \subsection{Il server: prima versione}
 \label{sec:TCPsimp_server_main}
 
-La prima versione del server, contenuta nel file \file{TCP\_echod.c}, è
-riportata in \figref{fig:TCP_echo_server_code}. Come abbiamo fatto per il
-client anche il server è stato diviso in un corpo principale, costituito dalla
-funzione \code{main}, che è molto simile a quello visto nel precedente esempio
-per il server del servizio \textit{daytime} di
+La prima versione del server, contenuta nel file \file{TCP\_echod_first.c}, è
+riportata in \figref{fig:TCP_echo_server_first_code}. Come abbiamo fatto per
+il client anche il server è stato diviso in un corpo principale, costituito
+dalla funzione \code{main}, che è molto simile a quello visto nel precedente
+esempio per il server del servizio \textit{daytime} di
 \secref{sec:TCP_daytime_cunc_server}, e da una funzione ausiliaria
 \code{ServEcho} che si cura della gestione del servizio.
 
 \begin{figure}[!htbp]
   \footnotesize \centering
   \begin{minipage}[c]{15.6cm}
-    \includecodesample{listati/TCP_echod.c}
+    \includecodesample{listati/TCP_echod_first.c}
   \end{minipage} 
   \normalsize
   \caption{Codice del corpo principale della prima versione del server
     per il servizio \textit{echo}.}
-  \label{fig:TCP_echo_server_code}
+  \label{fig:TCP_echo_server_first_code}
 \end{figure}
 
 In questo caso però, rispetto a quanto visto nell'esempio di
@@ -2003,16 +2003,79 @@ dei processi figli terminati gi
 Basterà allora aggiungere il seguente codice:
 \includecodesnip{listati/sigchildhand.c}
 \noindent
-all'esempio illustrato in \figref{fig:TCP_echo_server_code}.
+all'esempio illustrato in \figref{fig:TCP_echo_server_first_code}.
+
+In questo modo però si introduce un altro problema, il fatto che, come
+spiegato in \secref{sec:sig_gen_beha}, quando un programma si trova in stato
+di \texttt{sleep} durante l'esecuzione di una system call, questa viene
+interrotta alla ricezione di un segnale, per cui alla fine dell'esecuzione del
+gestore il programma, se questo ritorna, l'esecuzione del programma riprenderà
+con l'uscita dalla system call con un errore di \errcode{EINTR}. 
+
+Questo comporta che quando si chiude il client, con la terminazione del
+processo figlio, il padre, che riceve il segnale ed esegue il gestore,
+ritornerà dalla \func{accept} (a meno di un caso fortuito in cui il segnale
+arriva durante l'esecuzione del programma in risposta ad una connessione) con
+un errore di \errcode{EINTR}, terminando a sua volta con un errore del tipo:
+\begin{verbatim}
+[root@gont sources]# ./echod -i
+accept error: Interrupted system call
+\end{verbatim}%#
+
+
+Come accennato in \secref{sec:sig_gen_beha} questo ci mette di fronte a due
+possibili soluzioni, la più semplice è quella di modificare il codice di
+\func{Signal} per richiedere il riavvio automatico delle system call
+interrotte secondo la semantica di BSD, usando l'opzione \const{SA\_RESTART}
+di \func{sigaction}; rispetto a quanto visto in \figref{fig:sig_Signal_code}
+definiremo allora la nuova funzione \func{SignalRestart} come mostrato in
+\figref{fig:sig_SignalRestart_code}.
 
-In questo modo però si introduce un altro problema, 
+\begin{figure}[!htb]
+  \footnotesize  \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/SignalRestart.c}
+  \end{minipage}  
+  \normalsize 
+  \caption{La funzione \funcd{SignalRestart}, che installa un gestore di
+    segnali in semantica BSD per il riavvio delle system call interrotte.}
+  \label{fig:sig_SignalRestart_code}
+\end{figure}
 
+Come si può notare questa funzione è identica a \func{Signal}, solo che in
+questo caso invece di inizializzare a zero il campo \var{sa\_flags} di
+\struct{sigaction}, lo si inizializza (\texttt{\small 5}) al valore
+\const{SA\_RESTART}. Usando questa funzione al posto di \func{Signal} nel
+server non è necessaria nessuna altra modifica: le system call interrotte
+saranno automaticamente riavviate, e l'errore \errcode{EINTR} non si
+manifesterà più.
 
+La seconda soluzione è più invasiva e richiede di controllare tutte le volte
+l'errore restituito dalle varie system call, ripetendo la chiamata qualora
+questo corrisponda ad \errcode{EINTR}, questo comporta una riscrittura
+parziale del server secondo quanto mostrato in 
 
-\subsection{I vari scenari critici}
-\label{sec:TCP_echo_critical}
+\begin{figure}[!htbp]
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/TCP_echod.c}
+  \end{minipage} 
+  \normalsize
+  \caption{Codice del corpo principale della seconda versione del server
+    per il servizio \textit{echo}.}
+  \label{fig:TCP_echo_server_code}
+\end{figure}
 
 
+\section{I vari scenari critici}
+\label{sec:TCP_echo_critical}
+
+Con le modifiche viste in \secref{sec:TCP_child_hand} il nostro esempio
+diventa in grado di affrontare correttamente la gestione ordinaria delle
+connessioni, ma un server di rete deve tenere conto che, al contrario di
+quanto avviene per i server che operano nei confronti di processi presenti
+sulla stessa macchina, la rete è di sua natura inaffidabile, per cui è
+necessario essere in grado di gestire tutta una serie di situazioni critiche.