Commentato il codice del server echo basato sulla funzione poll.
authorSimone Piccardi <piccardi@gnulinux.it>
Tue, 17 Feb 2004 23:48:46 +0000 (23:48 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Tue, 17 Feb 2004 23:48:46 +0000 (23:48 +0000)
listati/poll_echod.c
sources/poll_echod.c
tcpsockadv.tex

index 91b53ce..8efef2f 100644 (file)
@@ -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 */
 }
index 9abccf4..c219299 100644 (file)
@@ -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);
 }
 /*
index c93dc4a..91a5ada 100644 (file)
@@ -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}