From: Simone Piccardi Date: Sun, 19 Oct 2003 10:38:27 +0000 (+0000) Subject: Corretto uso del file nel programma, inserite spiegazioni X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=af73295172df06a6a91edc4c206b6e5633c566f6;p=gapil.git Corretto uso del file nel programma, inserite spiegazioni --- diff --git a/listati/ClientEcho_third.c b/listati/ClientEcho_third.c index f1290ef..401ac5d 100644 --- a/listati/ClientEcho_third.c +++ b/listati/ClientEcho_third.c @@ -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; } diff --git a/sources/TCP_echo.c b/sources/TCP_echo.c index c8c5c1a..57d6184 100644 --- a/sources/TCP_echo.c +++ b/sources/TCP_echo.c @@ -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; } diff --git a/tcpsockadv.tex b/tcpsockadv.tex index 4498652..af33489 100644 --- a/tcpsockadv.tex +++ b/tcpsockadv.tex @@ -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}