From: Simone Piccardi Date: Tue, 17 Feb 2004 23:48:46 +0000 (+0000) Subject: Commentato il codice del server echo basato sulla funzione poll. X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=0605ed025fd00ee41a7515b778bc686a6044f059;p=gapil.git Commentato il codice del server echo basato sulla funzione poll. --- diff --git a/listati/poll_echod.c b/listati/poll_echod.c index 91b53ce..8efef2f 100644 --- a/listati/poll_echod.c +++ b/listati/poll_echod.c @@ -14,7 +14,6 @@ PrintErr("poll error"); exit(1); } - /* on activity */ if (poll_set[list_fd].revents & POLLRDNORM) { /* if new connection */ n--; /* decrement active */ len = sizeof(c_addr); /* and call accept */ @@ -25,7 +24,6 @@ poll_set[fd].fd = fd; /* set new connection socket */ if (max_fd < fd) max_fd = fd; /* if needed set new maximum */ } - /* loop on open connections */ i = list_fd; /* first socket to look */ while (n != 0) { /* loop until active */ i++; /* start after listening socket */ @@ -55,6 +53,5 @@ } } } - /* normal exit, never reached */ - exit(0); + exit(0); /* normal exit, never reached */ } diff --git a/sources/poll_echod.c b/sources/poll_echod.c index 9abccf4..c219299 100644 --- a/sources/poll_echod.c +++ b/sources/poll_echod.c @@ -26,7 +26,7 @@ * * Usage: echod -h give all info * - * $Id: poll_echod.c,v 1.2 2004/01/05 19:24:52 piccardi Exp $ + * $Id: poll_echod.c,v 1.3 2004/02/17 23:48:46 piccardi Exp $ * ****************************************************************/ /* @@ -236,8 +236,9 @@ void usage(void) { printf(" -h print this help\n"); printf(" -d write debug info\n"); printf(" -i use interactively\n"); - printf(" -c disable BSD semantics\n"); - printf(" -w N wait N sec. before calling accept\n"); + printf(" -c disable BSD signal semantics\n"); + printf(" -n N set max contemporary connection\n"); + printf(" -w N wait N sec. before calling poll\n"); exit(1); } /* diff --git a/tcpsockadv.tex b/tcpsockadv.tex index c93dc4a..91a5ada 100644 --- a/tcpsockadv.tex +++ b/tcpsockadv.tex @@ -750,8 +750,85 @@ ma la struttura del programma resta sostanzialmente la stessa. In \figref{fig:TCP_PollEchod} è riportata la sezione principale della nuova versione del server, la versione completa del codice è riportata nel file -\file{poll\_echod.c} dei sorgenti allegati alla guida. Al solito si sono -tralasciate +\file{poll\_echod.c} dei sorgenti allegati alla guida. Al solito nella figura +si sono tralasciate la gestione delle opzioni, la creazione del socket in +ascolto, la cessione dei privilegi e le operazioni necessarie a far funzionare +il programma come demone, privilegiando la sezione principale del programma. + +Come per il precedente server basato su \func{select} il primo passo +(\texttt{\small 2--8}) è quello di inizializzare le variabili necessarie. Dato +che in questo caso dovremo usare un vettore di strutture occorre anzitutto +(\texttt{\small 2}) allocare la memoria necessaria utilizzando il numero +massimo \var{n} di socket osservabili, che viene impostato attraverso +l'opzione \texttt{-n} ed ha un valore di default di 256. + +Dopo di che si preimposta (\texttt{\small 3}) il valore \var{max\_fd} del file +descriptor aperto con valore più alto a quello del socket in ascolto (al +momento l'unico), e si provvede (\texttt{\small 4--7}) ad inizializzare le +strutture, disabilitando (\texttt{\small 5}) l'osservazione con un valore +negativo del campo \var{fd} ma predisponendo (\texttt{\small 6}) il campo +\var{events} per l'osservazione dei dati normali con \const{POLLRDNORM}. +Infine (\texttt{\small 8}) si attiva l'osservazione del socket in ascolto +inizializzando la corrispondente struttura. Questo metodo comporta, in +modalità interattiva, lo spreco di tre strutture (quelle relative a standard +input, output ed error) che non vengono mai utilizzate in quanto la prima è +sempre quella relativa al socket in ascolto. + +Una volta completata l'inizializzazione tutto il lavoro viene svolto +all'interno del ciclo principale \texttt{\small 10--55}) che ha una struttura +sostanzialmente identica a quello usato per il precedente esempio basato su +\func{select}. La prima istruzione (\texttt{\small 11--12}) è quella di +eseguire \func{poll} all'interno di un ciclo che la ripete qualora venisse +interrotta da un segnale, da cui si esce soltanto quando la funzione ritorna, +restituendo nella variabile \var{n} il numero di file descriptor trovati +attivi. Qualora invece si sia ottenuto un errore si procede (\texttt{\small + 13--16}) alla terminazione immediata del processo provvedendo a stampare una +descrizione dello stesso. + +Una volta ottenuta dell'attività su un file descriptor si hanno di nuovo due +possibilità. La prima possibilità è che ci sia attività sul socket in ascolto, +indice di una nuova connessione, nel qual caso si controlla (\texttt{\small + 17}) se il campo \var{revents} della relativa struttura è attivo; se è così +si provvede (\texttt{\small 18}) a decrementare la variabile \var{n} (che +assume il significato di numero di file descriptor attivi rimasti da +controllare) per poi (\texttt{\small 19--23}) effettuare la chiamata ad +\func{accept}, terminando il processo in caso di errore. Se la chiamata ad +\func{accept} ha successo si procede attivando (\texttt{\small 24}) la +struttura relativa al nuovo file descriptor da essa ottenuto, modificando +(\texttt{\small 24}) infine quando necessario il valore massimo dei file +descriptor aperti mantenuto in \var{max\_fd}. + +La seconda possibilità è che vi sia dell'attività su uno dei socket aperti in +precedenza, nel qual caso si inizializza (\texttt{\small 27}) l'indice \var{i} +del vettore delle strutture \struct{pollfd} al valore del socket in ascolto, +dato che gli ulteriori socket aperti avranno comunque un valore superiore. Il +ciclo (\texttt{\small 28--54}) prosegue fintanto che il numero di file +descriptor attivi, mantenuto nella variabile \var{n}, è diverso da zero. Se +pertanto ci sono ancora socket attivi da individuare si comincia con +l'incrementare (\texttt{\small 30}) l'indice e controllare (\texttt{\small + 31}) se corrisponde ad un file descriptor in uso, analizzando il valore del +campo \var{fd} della relativa struttura, e chiudendo immediatamente il ciclo +qualora non lo sia. Se invece il file descriptor è in uso si verifica +(\texttt{\small 31}) se c'è stata attività controllando il campo +\var{revents}. + +Di nuovo se non si verifica la presenza di attività il ciclo si chiude subito, +altrimenti si provvederà (\texttt{\small 32}) a decrementare il numero \var{n} +di file descriptor attivi da controllare e ad eseguire (\texttt{\small 33}) la +lettura, ed in caso di errore (\texttt{\small 34--37}) al solito lo si +notificherà uscendo immediatamente. Qualora invece si ottenga una condizione +di end-of-file (\texttt{\small 38--47}) si provvederà a chiudere +(\texttt{\small 39}) anche il nostro capo del socket e a marcarlo +(\texttt{\small 40}) nella struttura ad esso associata come inutilizzato. +Infine dovrà essere ricalcolato (\texttt{\small 41--45}) un eventiale nuovo +valore di \var{max\_fd}. L'ultimo passo è (\texttt{\small 46}) chiudere il +ciclo in quanto in questo caso non c'è più niente da riscrivere all'indietro +sul socket. + +Se invece si sono letti dei dati si provvede (\texttt{\small 48}) ad +effettuarne la riscrittura all'indietro, con il solito controllo ed eventuale +uscita e notifica in caso si errore (\texttt{\small 49--52}). + \section{Le opzioni dei socket}