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 f1290ef091db9d02b0ba5c7a01b6e7266c483e47..401ac5df4580d9eaf132190682606ffa8bcf6d73 100644 (file)
@@ -6,17 +6,17 @@ void ClientEcho(FILE * filein, int socket)
     fd_set fset;
     /* initialize file descriptor set */
     FD_ZERO(&fset);
     fd_set fset;
     /* initialize file descriptor set */
     FD_ZERO(&fset);
-    maxfd = max(fileno(stdin), socket) + 1;
+    maxfd = max(fileno(filein), socket) + 1;
     while (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 */
        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 */
            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)); 
                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;
                }
                    printf("Errore in scrittura: %s", strerror(errno));
                    return;
                }
index c8c5c1ac97910381607852c971c5ce1c3203d11c..57d61840120e90adc83a046a274b62e4a3f1a9a4 100644 (file)
@@ -26,7 +26,7 @@
  *
  * Usage: echo -h give all info's
  *
  *
  * 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);
     fd_set fset;
     /* initialize file descriptor set */
     FD_ZERO(&fset);
-    maxfd = max(fileno(stdin), socket) + 1;
+    maxfd = max(fileno(filein), socket) + 1;
     while (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 */
        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 */
            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)); 
                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;
                }
                    printf("Errore in scrittura: %s", strerror(errno));
                    return;
                }
index 44986525fc3141b95422a22548adb4ede34b939a..af3348945068b2df47b195bb85105f81782a4e8f 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}.
 
 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à.
 
 \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
 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
 
 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.
 
 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})
 
 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
 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}
 
 
 \section{Le opzioni dei socket}