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 \nfig, è analoga a quella vista nel precedente esempio
-esaminato in \secref{sec:TCPelem_serv_code}.
+esaminato in \secref{sec:TCPel_cunc_serv}.
\begin{figure}[!htb]
\footnotesize
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:TCPelem_serv_code} sono che in questo caso per il socket in
+\figref{fig:TCPel_serv_code} sono che in questo caso per il socket in
ascolto viene usata la porta 7 e tutta la gestione della comunicazione è
delegata alla funzione \texttt{ServEcho}.
% Per ogni connessione viene creato un
\end{lstlisting}
\caption{Codice della prima versione della funzione \texttt{ServEcho} per la
gestione del servizio \texttt{echo}.}
- \label{fig:TCPsimpl_sockecho_code}
+ \label{fig:TCPsimpl_server_elem_sub}
\end{figure}
Quando il client chiude la connessione il ricevimento del FIN fa ritornare la
\subsection{Il client}
-\label{sec:TCPsimp_server_main}
+\label{sec:TCPsimp_client_main}
Il codice del client è riportato in \nfig, anche esso ricalca la struttura del
precedente client per il servizio \texttt{daytime} (vedi
}
\end{lstlisting}
\caption{Codice della prima versione del client \texttt{echo}.}
- \label{fig:TCPsimpl_sockecho_code}
+ \label{fig:TCPsimpl_client_elem}
\end{figure}
La funzione \texttt{main} si occupa della creazione del socket e della
\end{lstlisting}
\caption{Codice della prima versione della funzione \texttt{ClientEcho} per
la gestione del servizio \texttt{echo}.}
- \label{fig:TCPsimpl_sockecho_code}
+ \label{fig:TCPsimpl_client_echo_sub}
\end{figure}
La funzione utilizza due buffer per gestire i dati inviati e letti sul socket
\begin{itemize}
\item il client chiama la funzione \texttt{ClientEcho} che si blocca sulla
\texttt{fgets} dato che non si è ancora scritto nulla sul terminale.
-\item il server eseguirà una \texttt{fork} facendo chiamare al processo figlo
+\item il server eseguirà una \texttt{fork} facendo chiamare al processo figlio
la funzione \texttt{ServEcho}, quest'ultima si bloccherà sulla \texttt{read}
dal socket sul quale ancora non sono presenti dati.
\item il processo padre del server chiamerà di nuovo \texttt{accept}
\subsection{La conclusione normale}
-\label{sec:TCPsimpl_startup}
+\label{sec:TCPsimpl_conclusion}
Tutto quello che scriveremo sul client sarà rimandato indietro dal server e
ristampato a video fintanto che non concluderemo l'immissione dei dati; una
casi seguenti:
\begin{enumerate}
-\item Inviando un carattere di EOF da terminale la \texttt{fgets} ritorna
+\item inviando un carattere di EOF da terminale la \texttt{fgets} ritorna
restituendo un puntatore nullo che causa l'uscita dal ciclo di
\texttt{while}, così la \texttt{ClientEcho} ritorna.
-\item Al ritorno di \texttt{ClientEcho} ritorna anche la funzione
+\item al ritorno di \texttt{ClientEcho} ritorna anche la funzione
\texttt{main}, e come parte del processo terminazione tutti i file
descriptor vengono chiusi (si ricordi quanto visto in
\secref{sec:proc_term_conclusion}), il che causa la chiusura del socket di
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}).
-\item Quando il server riceve il FIN la la \texttt{read} del processo figlio
+\item quando il server riceve il FIN la la \texttt{read} del processo figlio
che gestisce la connessione ritorna restituendo 0 causando così l'uscita dal
ciclo di \texttt{while} e il ritorno di \texttt{ServEcho}, a questo punto il
processo figlio termina chiamando \texttt{exit}.
-\item All'uscita del figlio tutti i file descriptor vengono chiusi, la
+\item all'uscita del figlio tutti i file descriptor vengono chiusi, la
chiusura del socket connesso fa sì che venga effettuata la sequenza finale
di chiusura della connessione, viene emesso un FIN dal server che riceverà
un ACK dal client, a questo punto la connessione è conclusa e il client
\end{enumerate}
+\subsection{La gestione dei processi figli}
+\label{sec:TCPsimpl_child_hand}
-
+Tutto questo riguarda la connessione, c'è però un'altro effetto del
+procedimento di chiusura del processo figlio nel server, e cioè l'invio del
+segnale \texttt{SIGCHILD} al padre. Dato che non si è installato un
+manipolatore (vedi \secref{cha:signals} per le problematiche relative) e che
+l'azione di default per questo segnale è quella di essere ignorato quello che
+avremo è che il processo figlio entrerà nello stato di zombie, come risulta
+una volta che ripetiamo il comando \texttt{ps}:
\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à gestire il segnale, per questo installeremo un
+manipolatore usando la funzione \texttt{Signal} (trattata in dettaglio in
+\secref{sec:sig_signal}).
+