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;
}
*
* 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 $
*
****************************************************************/
/*
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;
}
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 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}