Corretto uso del file nel programma, inserite spiegazioni
authorSimone Piccardi <piccardi@gnulinux.it>
Sun, 19 Oct 2003 10:38:27 +0000 (10:38 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sun, 19 Oct 2003 10:38:27 +0000 (10:38 +0000)
listati/ClientEcho_third.c
sources/TCP_echo.c
tcpsockadv.tex

index f1290ef..401ac5d 100644 (file)
@@ -6,17 +6,17 @@ void ClientEcho(FILE * filein, int socket)
     fd_set fset;
     /* initialize file descriptor set */
     FD_ZERO(&fset);
-    maxfd = max(fileno(stdin), socket) + 1;
+    maxfd = max(fileno(filein), socket) + 1;
     while (1) {
-       FD_SET(socket, &fset);        /* set for the socket */
-       FD_SET(fileno(stdin), &fset); /* set for the standard input */
+       FD_SET(socket, &fset);         /* set for the socket */
+       FD_SET(fileno(filein), &fset); /* set for the standard input */
        select(maxfd, &fset, NULL, NULL, NULL); /* wait for read ready */
-       if (FD_ISSET(fileno(stdin), &fset)) {   /* if ready on stdin */
+       if (FD_ISSET(fileno(filein), &fset)) {  /* if ready on stdin */
            if (fgets(sendbuff, MAXLINE, filein) == NULL) { /* if no input */
-               return;               /* we stopped client */
-           } else {                  /* else we have to write to socket */
+               return;                /* we stopped client */
+           } else {                   /* else we have to write to socket */
                nwrite = FullWrite(socket, sendbuff, strlen(sendbuff)); 
-               if (nwrite < 0) {     /* on error stop */
+               if (nwrite < 0) {      /* on error stop */
                    printf("Errore in scrittura: %s", strerror(errno));
                    return;
                }
index c8c5c1a..57d6184 100644 (file)
@@ -26,7 +26,7 @@
  *
  * Usage: echo -h give all info's
  *
- * $Id: TCP_echo.c,v 1.9 2003/10/18 16:30:23 piccardi Exp $
+ * $Id: TCP_echo.c,v 1.10 2003/10/19 10:38:27 piccardi Exp $
  *
  ****************************************************************/
 /* 
@@ -144,17 +144,17 @@ void ClientEcho(FILE * filein, int socket)
     fd_set fset;
     /* initialize file descriptor set */
     FD_ZERO(&fset);
-    maxfd = max(fileno(stdin), socket) + 1;
+    maxfd = max(fileno(filein), socket) + 1;
     while (1) {
-       FD_SET(socket, &fset);        /* set for the socket */
-       FD_SET(fileno(stdin), &fset); /* set for the standard input */
+       FD_SET(socket, &fset);         /* set for the socket */
+       FD_SET(fileno(filein), &fset); /* set for the standard input */
        select(maxfd, &fset, NULL, NULL, NULL); /* wait for read ready */
-       if (FD_ISSET(fileno(stdin), &fset)) {   /* if ready on stdin */
+       if (FD_ISSET(fileno(filein), &fset)) {  /* if ready on stdin */
            if (fgets(sendbuff, MAXLINE, filein) == NULL) { /* if no input */
-               return;               /* we stopped client */
-           } else {                  /* else we have to write to socket */
+               return;                /* we stopped client */
+           } else {                   /* else we have to write to socket */
                nwrite = FullWrite(socket, sendbuff, strlen(sendbuff)); 
-               if (nwrite < 0) {     /* on error stop */
+               if (nwrite < 0) {      /* on error stop */
                    printf("Errore in scrittura: %s", strerror(errno));
                    return;
                }
index 4498652..af33489 100644 (file)
@@ -184,10 +184,10 @@ le modalit
 assolutamente identico. La nostra nuova versione di \func{ClientEcho}, la
 terza della serie, è riportata in \figref{fig:TCP_ClientEcho_third}.
 
-In questo caso la funzione comincia (\texttt{\small 8--9}) con la
-cancellazione del file descriptor set \var{fset} e del valore \var{maxfd} da
-passare a \func{select} come massimo per il numero dei file descriptor. Per
-quest'ultimo si usa la macro \code{max} definita nel nostro file
+In questo caso la funzione comincia (\texttt{\small 8--9}) con l'azzeramento
+del file descriptor set \var{fset} e l'impostazione del valore \var{maxfd}, da
+passare a \func{select} come massimo per il numero di file descriptor. Per
+determinare quest'ultimo si usa la macro \code{max} definita nel nostro file
 \file{macro.h} che raccoglie una collezione di macro di preprocessore di varia
 utilità.
 
@@ -197,29 +197,47 @@ viene ripetuto indefinitamente. Per ogni ciclo si reinizializza
 file descriptor associato al socket \var{socket} e per lo standard input (il
 cui valore si recupera con la funzione \func{fileno}). Questo è necessario in
 quanto la successiva (\texttt{\small 13}) chiamata a \func{select} comporta
-una modifica dei due bit relativi, che quindi devono essere reimpostati.
+una modifica dei due bit relativi, che quindi devono essere reimpostati
+all'inizio di ogni ciclo.
 
 Si noti come la chiamata a \func{select} venga eseguita usando come primo
-argomento il valore di \var{maxfd}, precedentemente calcolato, passando poi il
-solo file descriptor set per il controllo dell'attività in lettura, gli altri
-argomenti sono tutti passati come puntatori nulli non interessando né il
+argomento il valore di \var{maxfd}, precedentemente calcolato, e passando poi
+il solo file descriptor set per il controllo dell'attività in lettura, negli
+altri argomenti sono passati tutti puntatori nulli, non interessando né il
 controllo delle altre attività, né l'impostazione di un valore di timeout.
 
-Al ritorno di \func{select} si provvede a controllare quale dei file
-descriptor presneta attività, si comincia (\texttt{\small 14--24}) con il file
-descriptor associato allo standard input. In caso di attività (quando cioè
-\macro{FD_ISSET} ritorna una valore diverso da zero) si esegue (\texttt{\small
-  15}) una \func{fgets} per leggere gli eventuali dati presenti; se non ve ne
-sono (e la funzione restituisce pertanto un puntatore nullo) si ritorna
-immediatamente (\texttt{\small 16}) dato che questo significa che si è chiuso
-lo standard input; altrimenti (\texttt{\small 18--22}) si scrivono i dati sul
-socket, uscendo immediatamente in caso di errore di scrittura.
+Al ritorno di \func{select} si provvede a controllare quale dei due file
+descriptor presenta attività in lettura, cominciando (\texttt{\small 14--24})
+con il file descriptor associato allo standard input. In caso di attività
+(quando cioè \macro{FD\_ISSET} ritorna una valore diverso da zero) si esegue
+(\texttt{\small 15}) una \func{fgets} per leggere gli eventuali dati presenti;
+se non ve ne sono (e la funzione restituisce pertanto un puntatore nullo) si
+ritorna immediatamente (\texttt{\small 16}) dato che questo significa che si è
+chiuso lo standard input e quindi concluso l'utilizzo del client; altrimenti
+(\texttt{\small 18--22}) si scrivono i dati appena letti sul socket,
+prevedendo una uscita immediata in caso di errore di scrittura.
 
 Controllato lo standard input si passa a controllare (\texttt{\small 25--40})
-il socket connesso, in caso di attività si esegue (\texttt{\small 26}) subito
+il socket connesso, in caso di attività (\texttt{\small 26}) si esegue subito
 una \func{read} di cui si controlla il valore di ritorno; se questo è negativo
 (\texttt{\small 27--30}) si è avuto un errore e pertanto si esce
-immediatamente segnalandolo, se è nullo (\texttt{\small 31--34}) 
+immediatamente segnalandolo, se è nullo (\texttt{\small 31--34}) significa che
+il server ha chiuso la connessione, e di nuovo si esce con stampando prima un
+messaggio di avviso, altrimenti (\texttt{\small 35--39}) si effettua la
+terminazione della stringa e la si stampa a sullo standard output (uscendo in
+caso di errore), per ripetere il ciclo da capo.
+
+Con questo meccanismo il programma invece di essere bloccato in lettura sullo
+standard input resta bloccato sulla \func{select}, che ritorna soltanto quando
+viene rilevata attività su uno dei due file descriptor posti sotto controllo.
+Questo di norma avviene solo quando si è scritto qualcosa sullo standard
+input, o quando si riceve dal socket la risposta a quanto si era appena
+scritto. Ma adesso il client diventa capace di accorgersi immediatamente della
+terminazione del server; in tal caso infatti il server chiuderà il socket
+connesso, ed alla ricezione del FIN la funzione \func{select} ritornerà (come
+illustrato in \secref{sec:TCP_sock_select}) segnalando una condizione di end
+of file, per cui il nostro client potrà uscire immediatamente.
+
 
 
 \section{Le opzioni dei socket}