X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=elemtcp.tex;h=90fcfb942272ba3a92f8f4cb2fbc8b5dba8a8391;hp=534dd398f18819943c1811ed5bbb63fcf5d556ab;hb=3e8003adb1396080659ef5d34896eb2f573be6cd;hpb=7444bbe1f4d1e9858693bfcb41921fa601450a89 diff --git a/elemtcp.tex b/elemtcp.tex index 534dd39..90fcfb9 100644 --- a/elemtcp.tex +++ b/elemtcp.tex @@ -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.