From: Simone Piccardi Date: Thu, 19 Jun 2003 11:43:13 +0000 (+0000) Subject: Altro lavoro sul server echo, e sulle condizioni particolari X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=bf66d833fbcd76d007d1d748217b2cea773d4a39 Altro lavoro sul server echo, e sulle condizioni particolari --- diff --git a/elemtcp.tex b/elemtcp.tex index 585f605..cfc4c85 100644 --- a/elemtcp.tex +++ b/elemtcp.tex @@ -1328,7 +1328,7 @@ Il primo passo (\texttt{\small 14--18}) \func{socket} ritorna il descrittore che viene usato per identificare il socket in tutte le chiamate successive. Nel caso la chiamata fallisca si stampa un errore (\texttt{\small 16}) con la funzione \func{perror} e si esce -(\texttt{\small 16}) con un codice di errore. +(\texttt{\small 17}) con un codice di errore. Il passo seguente (\texttt{\small 19--27}) è quello di costruire un'apposita struttura \struct{sockaddr\_in} in cui sarà inserito l'indirizzo del server ed @@ -2114,16 +2114,20 @@ la rete gestire tutta una serie di situazioni critiche che non esistono per i processi locali. -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}; questo significa che, oltre al caso di interruzione -da parte di un segnale, esistono altri errori non fatali che necessitano -semplicemente la ripetizione della chiamata senza che si debba uscire dal -programma. Un esempio possibile è quello mostrato in -\figref{fig:TCP_early_abort}, in cui la connessione viene abortita dal client -con l'invio di un segmento RST prima che sia stata chiamata la funzione -\func{accept}. - +La prima situazione critica è quella della terminazione precoce, per via di un +qualche errore di 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}. + +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}. \begin{figure}[htb] \centering @@ -2132,6 +2136,30 @@ con l'invio di un segmento RST prima che sia stata chiamata la funzione \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. + + +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. + +In questo caso + %%% Local Variables: diff --git a/html/index.html b/html/index.html index 6527164..f39abd8 100644 --- a/html/index.html +++ b/html/index.html @@ -115,7 +115,7 @@ attenzione particolare alle GNU libc, che sono la versione più usata delle librerie del C, senza dimenticare, ove note, di citare le differenze con possibili alternative come le libc5 o - le ulibc. + le uclibc.

L'obiettivo resta comunque quello di riuscire a produrre una @@ -144,7 +144,7 @@ all'opera di Mirko Maischberger abbiamo anche una bellissima versione HTML, accessibile nella sezione On Line , finalemente + face="sans-serif"> online , finalmente all'altezza della versione stampabile.

diff --git a/img/endianess.dia b/img/endianess.dia index 2d88d94..8b309a8 100644 Binary files a/img/endianess.dia and b/img/endianess.dia differ diff --git a/socket.tex b/socket.tex index 4adb5c7..3315352 100644 --- a/socket.tex +++ b/socket.tex @@ -732,12 +732,11 @@ cos \label{sec:sock_addr_func} In questa sezione tratteremo delle varie funzioni usate per manipolare gli -indirizzi, limitandoci però agli indirizzi internet. - -Come accennato gli indirizzi e i numeri di porta usati nella rete devono -essere forniti in formato opportuno (il \textit{network order}). Per capire -cosa significa tutto ciò occorre introdurre un concetto generale che tornerà -utile anche in seguito. +indirizzi, limitandoci però agli indirizzi internet. Come accennato gli +indirizzi e i numeri di porta usati nella rete devono essere forniti in +formato opportuno (il \textit{network order}). Per capire cosa significa tutto +ciò occorre introdurre un concetto generale che tornerà utile anche in +seguito. \subsection{La \textit{endianess}\index{endianess}} @@ -762,7 +761,7 @@ parte dal bit meno significativo \begin{figure}[htb] \centering - \includegraphics[height=5cm]{img/endianess} + \includegraphics[height=3cm]{img/endianess} \caption{Schema della disposizione dei dati in memoria a seconda della \textit{endianess}\index{endianess}.} \label{fig:sock_endianess} @@ -788,15 +787,11 @@ questi cambiamenti. Il problema connesso all'endianess\index{endianess} è che quando si passano dei dati da un tipo di architettura all'altra i dati vengono interpretati in maniera diversa, e ad esempio nel caso dell'intero a 16 bit ci si ritroverà -con i due byte in cui è suddiviso scambiati di posto, e ne sarà quindi -invertito l'ordine di lettura per cui, per riavere il valore originale, -dovranno essere rovesciati. - -Per questo motivo si usano delle funzioni di conversione che servono a tener -conto automaticamente della possibile differenza fra l'ordinamento usato sul -computer e quello che viene usato nelle trasmissione sulla rete; queste -funzioni sono \funcd{htonl}, \funcd{htons}, \funcd{ntohl} e \funcd{ntohs} ed i -rispettivi prototipi sono: +con i due byte in cui è suddiviso scambiati di posto. Per questo motivo si +usano delle funzioni di conversione che servono a tener conto automaticamente +della possibile differenza fra l'ordinamento usato sul computer e quello che +viene usato nelle trasmissione sulla rete; queste funzioni sono \funcd{htonl}, +\funcd{htons}, \funcd{ntohl} e \funcd{ntohs} ed i rispettivi prototipi sono: \begin{functions} \headdecl{netinet/in.h} \funcdecl{unsigned long int htonl(unsigned long int hostlong)} diff --git a/sources/TCP_echod.c b/sources/TCP_echod.c index 08d926f..35de97c 100644 --- a/sources/TCP_echod.c +++ b/sources/TCP_echod.c @@ -26,7 +26,7 @@ * * Usage: echod -h give all info * - * $Id: TCP_echod.c,v 1.4 2003/06/18 21:19:24 piccardi Exp $ + * $Id: TCP_echod.c,v 1.5 2003/06/19 11:43:13 piccardi Exp $ * ****************************************************************/ /* @@ -60,7 +60,9 @@ int main(int argc, char *argv[]) int list_fd, conn_fd; int waiting; pid_t pid; - struct sockaddr_in serv_add; + struct sockaddr_in serv_add, cli_add; + socklen_t len; + char debug[MAXLINE], ipaddr[20]; /* * Input section: decode parameters passed in the calling * Use getopt function @@ -142,12 +144,21 @@ int main(int argc, char *argv[]) /* handle echo to client */ while (1) { /* accept connection */ - while (((conn_fd = accept(list_fd, NULL, NULL)) < 0) - && (errno == EINTR)); + while (((conn_fd = accept(list_fd, (struct sockaddr *)&cli_add, &len)) + < 0) && (errno == EINTR)); if ( conn_fd < 0) { PrintErr("accept error"); exit(1); } + if (debugging) { + inet_ntop(AF_INET, &cli_add.sin_addr, ipaddr, sizeof(ipaddr)); + snprintf(debug, MAXLINE, "Accepted connection form %s\n", ipaddr); + if (demonize) { + syslog(LOG_DEBUG, debug); + } else { + printf("%s", debug); + } + } /* fork to handle connection */ if ( (pid = fork()) < 0 ){ PrintErr("fork error"); @@ -190,7 +201,7 @@ void ServEcho(int sockfd) { if (debugging) { buffer[nread] = 0; snprintf(debug, MAXLINE+20, "Letti %d byte, %s", nread, buffer); - if (demonize) { /* go daemon */ + if (demonize) { /* daemon mode */ syslog(LOG_DEBUG, debug); } else { printf("%s", debug); @@ -203,7 +214,7 @@ void ServEcho(int sockfd) { * routine to print error on stout or syslog */ void PrintErr(char * error) { - if (demonize) { /* go daemon */ + if (demonize) { /* daemon mode */ syslog(LOG_ERR, error); } else { perror(error);