%% elemtcp.tex
%%
-%% Copyright (C) 2000-2002 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2003 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",
\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
\label{sec:TCP_echo_client}
Il codice della prima versione del client per il servizio \textit{echo},
-disponibile nel file \file{TCP\_echo1.c}, è riportato in
+disponibile nel file \file{TCP\_echo\_first.c}, è riportato in
\figref{fig:TCP_echo_client_1}. Esso ricalca la struttura del precedente
client per il servizio \textit{daytime} (vedi
\secref{sec:TCP_daytime_client}), e la prima parte (\texttt{\small 10--27}) è
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15.6 cm}
- \includecodesample{listati/TCP_echo1.c}
+ \includecodesample{listati/TCP_echo_first.c}
\end{minipage}
\normalsize
\caption{Codice della prima versione del client \textit{echo}.}
di Linux questa è disponibile.} anche quando questa è presente, non è detto
possa essere usata con \func{accept}. La portabilità però viene al costo di
una riscrittura parziale del server, secondo quanto mostrato in
-\figref{fig:TCP_echo_server_code}.
+\figref{fig:TCP_echo_server_code}, dove si è riportata la sezione di codice
+modificata per la seconda versione del programma.
-\begin{figure}[!htbp]
+\begin{figure}[!htb]
\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}.}
+ \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}
padre in stato di sleep.\footnote{si noti infatti che le altre \textit{slow
system call} o sono chiamate prima di entrare nel ciclo principale, quando
ancora non esistono processi figli, o sono chiamate dai figli stessi.} Per
-questo l'unica modifica nella nuova versione del server, rispetto alla
-versione precedente vista in \figref{fig:TCP_ServEcho}, è nella sezione
-(\texttt{\small 43--48}) in cui si effettua la chiamata di \func{accept}.
-Quest'ultima allora viene effettuata (\texttt{\small 43--44}) all'interno di
-un ciclo di \code{while}\footnote{la sintassi del C relativa a questo ciclo
- può non essere del tutto chiara. In questo caso infatti si è usato un ciclo
- vuoto che non esegue nessuna istruzione, in questo modo quello che viene
- ripetuto con il ciclo è soltanto il codice che esprime la condizione
- all'interno del \code{while}.} che la ripete indefinitamente qualora in
-caso di errore il valore di \var{errno} sia \errcode{EINTR}. Negli altri casi
-si esce in caso di errore effettivo (\texttt{\small 45--48}), altrimenti il
-programma prosegue esattamente allo stesso modo del precedente.
-
+questo l'unica modifica sostanziale nella nuova versione del server, rispetto
+alla versione precedente vista in \figref{fig:TCP_ServEcho}, è nella sezione
+(\texttt{\small 9--14}) in cui si effettua la chiamata di \func{accept}.
+Quest'ultima viene effettuata (\texttt{\small 9--10}) all'interno di un ciclo
+di \code{while}\footnote{la sintassi del C relativa a questo ciclo può non
+ essere del tutto chiara. In questo caso infatti si è usato un ciclo vuoto
+ che non esegue nessuna istruzione, in questo modo quello che viene ripetuto
+ con il ciclo è soltanto il codice che esprime la condizione all'interno del
+ \code{while}.} che la ripete indefinitamente qualora in caso di errore il
+valore di \var{errno} sia \errcode{EINTR}. Negli altri casi si esce in caso di
+errore effettivo (\texttt{\small 11--14}), altrimenti il programma prosegue.
+
+Si noti che in questa nuova versione si è aggiunta una ulteriore sezione
+(\texttt{\small 15--28}) per il debugging, che stampa l'indirizzo da cui si è
+avuta la connessione, e la gestione (\texttt{\small 5}) di una nuova opzione,
+specificabile con \code{-w Nsec}, che inizializza la variabile \var{waiting}
+al numero di secondi da aspettare. Questa opzione permette di specificare un
+tempo di attesa prima di passare alla chiamata \func{accept}, il cui scopo
+sarà più chiaro facendo riferimento al primo degli scenari critici di
+\secref{sec:TCP_echo_critical}.
gestire tutta una serie di situazioni critiche che non esistono per i processi
locali.
-La prima situazione critica è quella della terminazione precoce, per via di un
-qualche errore di rete, della connessione effettuata da un client. Come
+
+\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}.
+\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.
-Questo significa che, oltre alla interruzione da parte di un segnale, che
-abbiamo trattato in \secref{sec:TCP_child_hand} nel caso particolare di
-\const{SIGCHLD}, si possono avere altri errori non fatali all'uscita di
-\func{accept}, che necessitano semplicemente la ripetizione della chiamata
-senza che si debba uscire dal programma. Uno scenario tipo è 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}.
+È 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 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
\label{fig:TCP_early_abort}
\end{figure}
-Benché questo non sia un fatto comune un evento simile può essere osservato
-con dei server molto occupati. In tal caso, in 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 \func{accept}. In questo caso si ha una situazione analoga a quella
-illustrata in \figref{fig:TCP_early_abort}, la connessione viene stabilita, ma
-subito dopo si ha una condizione
-
-
-che, come nell'esempio in figura, ritornerebbe
-immediatamente con un errore relativo alla connessione abortita.
+Benché questo non sia un fatto comune, un evento simile può essere osservato
+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 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.
+Questo significa che, oltre alla interruzione da parte di un segnale, che
+abbiamo trattato in \secref{sec:TCP_child_hand} nel caso particolare di
+\const{SIGCHLD}, si possono ricevere altri errori non fatali all'uscita 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. 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.
+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.
+
+
-In questo caso