ALcune correzioni sparse, risistemati i commenti interni delle varie
authorSimone Piccardi <piccardi@gnulinux.it>
Sat, 20 Nov 2004 19:01:21 +0000 (19:01 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sat, 20 Nov 2004 19:01:21 +0000 (19:01 +0000)
versione del client echo, iniziato a scrivere un insieme di funzioni per la
creazione di socket e connessioni generiche.

ChangeLog
sockctrl.tex
sources/SockAddr.c [new file with mode: 0644]
sources/TCP_echo_first.c
sources/TCP_echo_fourth.c [new file with mode: 0644]
sources/TCP_echo_second.c
sources/TCP_echo_third.c
system.tex
tcpsock.tex

index 6e6c9e2..7af790e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-11-20  Simone Piccardi  <piccardi@gont.earthsea.ea>
+
+       * system.tex: correzione di Alberto Pollastro sulla divisione,
+       invece che moltiplicazione, per CLOCK_PER_SEC del risultato di
+       clock(). 
+
 2004-06-02  Simone Piccardi  <piccardi@gont.earthsea.ea>
 
        * fileintro.tex: aggiunta nota di chiarimento sulla struttura
index b866442..62fd3d7 100644 (file)
@@ -1199,16 +1199,18 @@ forniscono una interfaccia sufficientemente generica.
 Inoltre in genere quando si ha a che fare con i socket non esiste soltanto il
 problema della risoluzione del nome che identifica la macchina, ma anche
 quello del servizio a cui ci si vuole rivolgere.  Per questo motivo con lo
-standard Posix 1003.1-2001 sono state indicate come deprecate le varie
+standard POSIX 1003.1-2001 sono state indicate come deprecate le varie
 funzioni \func{gethostbyaddr}, \func{gethostbyname}, \var{getipnodebyname} e
 \var{getipnodebyaddr} ed è stata introdotta una interfaccia completamente
 nuova.
 
-La prima funzione di questa interfaccia è \funcd{getaddrinfo}, che combina le
+La prima funzione di questa interfaccia è \funcd{getaddrinfo},\footnote{la
+  funzione è definita, insieme a \func{getnameinfo} che vedremo più avanti,
+  nell'\href{http://www.ietf.org/rfc/rfc2553.txt} {RFC~2553}.} che combina le
 funzionalità delle precedenti \func{getipnodebyname}, \func{getipnodebyaddr},
 \func{getservbyname} e \func{getservbyport}, consentendo di ottenere
 contemporaneamente sia la risoluzione di un indirizzo simbolico che del nome
-un servizio; il suo prototipo è:
+di un servizio; il suo prototipo è:
 \begin{functions}
   \headdecl{netdb.h} 
   \headdecl{sys/socket.h} 
@@ -1230,16 +1232,16 @@ forma \textit{dotted-decimal} per IPv4 o in formato esadecimale per IPv6.  Si
 può anche specificare il nome di una rete invece che di una singola macchina.
 Il secondo argomento, \param{service}, specifica invece il nome del servizio
 che si intende risolvere. Per uno dei due argomenti si può anche usare il
-valore \const{NULL}, nel qual caso la risoluzione verrà effettuata utilizzando
-soltantoo sulla base del valore dell'altro.
+valore \const{NULL}, nel qual caso la risoluzione verrà effettuata soltanto
+sulla base del valore dell'altro.
 
 Il terzo argomento, \param{hints}, deve essere invece un puntatore ad una
 struttura \struct{addrinfo} usata per dare dei \textsl{suggerimenti} al
 procedimento di risoluzione riguardo al protocollo o del tipo di socket che si
-intenderà utilizzare; la funzione infatti permette di effettuare ricerche
-generiche sugli indirizzi, usando sia IPv4 che IPv6, e richiedere risoluzioni
-sui nomi dei servizi indipendentemente dal protocollo (ad esempio TCP o UDP)
-che questi possono utilizzare.
+intenderà utilizzare; \func{getaddrinfo} infatti permette di effettuare
+ricerche generiche sugli indirizzi, usando sia IPv4 che IPv6, e richiedere
+risoluzioni sui nomi dei servizi indipendentemente dal protocollo (ad esempio
+TCP o UDP) che questi possono utilizzare.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1257,7 +1259,7 @@ La struttura \struct{addrinfo}, la cui definizione\footnote{la definizione 
   per il campo \var{ai\_addrlen}, qui viene usata quanto previsto dallo
   standard POSIX, in cui viene utilizzato \type{socklen\_t}; i due tipi di
   dati sono comunque equivalenti.} è riportata in
-fig.~\ref{fig:sock_addrinfo_struct} viene usata sia in ingresso, per passare
+fig.~\ref{fig:sock_addrinfo_struct}, viene usata sia in ingresso, per passare
 dei valori di controllo alla funzione, che in uscita, per ricevere i
 risultati. Il primo campo, \var{ai\_flags}, è una maschera binaria di bit che
 permettono di controllare le varie modalità di risoluzione degli indirizzi,
@@ -1272,10 +1274,10 @@ Tutti i campi seguenti vengono usati soltanto in uscita; il campo
 \var{ai\_addrlen} indica la dimensione della struttura degli indirizzi
 ottenuta come risultato, il cui contenuto sarà memorizzato nella struttura
 \struct{sockaddr} posta all'indirizzo puntato dal campo \var{ai\_addr}. Il
-campo \var{ai\_canonname} è il puntatore alla stringa contenente il nome
+campo \var{ai\_canonname} è un puntatore alla stringa contenente il nome
 canonico della macchina, ed infine, quando la funzione restituisce più di un
-risultato, \var{ai\_next} è il puntatore alla struttura \struct{addrinfo}
-successiva della lista.
+risultato, \var{ai\_next} è un puntatore alla successiva struttura
+\struct{addrinfo} della lista.
 
 Ovviamente non è necessario dare dei suggerimenti in ingresso, ed usando
 \const{NULL} come valore per l'argomento \param{hints} si possono compiere
@@ -1288,10 +1290,10 @@ I due campi \var{ai\_family} e \var{ai\_socktype} prendono gli stessi valori
 degli analoghi argomenti della funzione \func{socket}; in particolare per
 \var{ai\_family} si possono usare i valori di tab.~\ref{tab:net_pf_names} ma
 sono presi in considerazione solo \const{PF\_INET} e \const{PF\_INET6}, mentre
-se non si vuole specificare questo nessuna famiglia di indirizzi si può usare
-il valore \const{PF\_UNSPEC}.  Allo stesso modo per \var{ai\_socktype} si
-possono usare i valori illustrati sez.~\ref{sec:sock_type} per indicare per
-quale tipo di socket si vuole risolvere il servizio indicato, anche se i soli
+se non si vuole specificare nessuna famiglia di indirizzi si può usare il
+valore \const{PF\_UNSPEC}.  Allo stesso modo per \var{ai\_socktype} si possono
+usare i valori illustrati in sez.~\ref{sec:sock_type} per indicare per quale
+tipo di socket si vuole risolvere il servizio indicato, anche se i soli
 significativi sono \const{SOCK\_STREAM} e \const{SOCK\_DGRAM}; in questo caso,
 se non si vuole effettuare nessuna risoluzione specifica, si potrà usare un
 valore nullo.
@@ -1359,12 +1361,12 @@ bit della maschera.
 
 Come ultimo argomento di \func{getaddrinfo} deve essere passato un puntatore
 ad una variabile (di tipo puntatore ad una struttura \struct{addrinfo}) che
-verrà utilizzata dalla funzione per restituire (come \textit{value result
+verrà utilizzata dalla funzione per riportare (come \textit{value result
   argument}) i propri risultati. La funzione infatti è rientrante, ed alloca
 autonomamente tutta la memoria necessaria in cui verranno riportati i
-risultati della risoluzione.  La funzione restituisce in \param{res} il
-puntatore alla prima di una \textit{linked list} di strutture di tipo
-\struct{addrinfo} contenenti tutte le informazioni ottenute.
+risultati della risoluzione.  La funzione scriverà in \param{res} il puntatore
+iniziale ad una \textit{linked list} di strutture di tipo \struct{addrinfo}
+contenenti tutte le informazioni ottenute.
 
 La funzione restituisce un valore nullo in caso di successo, o un codice in
 caso di errore. I valori usati come codice di errore sono riportati in
@@ -1396,7 +1398,8 @@ corrispondente 
                            altri tipi di socket. \\
     \const{EAI\_ADDRFAMILY}& la rete richiesta non ha nessun indirizzo di rete
                            per la famiglia di indirizzi specificata. \\
-    \const{EAI\_NODATA}  & la . \\
+    \const{EAI\_NODATA}  & la macchina specificata esiste, ma non ha nessun
+                           indirizzo di rete definito. \\
     \const{EAI\_MEMORY}  & è stato impossibile allocare la memoria necessaria
                            alle operazioni. \\
     \const{EAI\_FAIL}    & il DNS ha restituito un errore di risoluzione  
@@ -1493,11 +1496,10 @@ canonico che 
 La scansione viene ripetuta (\texttt{\small 14}) fintanto che si ha un
 puntatore valido. La selezione principale è fatta sul campo \var{ai\_family},
 che stabilisce a quale famiglia di indirizzi fa riferimento la struttura in
-esame. Le possibilità sono due, un indirizzo IPv4 (\texttt{\small 15}) o IPv6
-(\texttt{\small 21}), se nessuna delle due si verifica si provvede
-(\texttt{\small 27--30}) a stampare un messaggio di errore ed
-uscire.\footnote{questa eventualità non dovrebbe mai verificarsi, almeno
-  fintanto che la funzione \func{getaddrinfo} lavora correttamente.}
+esame. Le possibilità sono due, un indirizzo IPv4 o IPv6, se nessuna delle due
+si verifica si provvede (\texttt{\small 27--30}) a stampare un messaggio di
+errore ed uscire.\footnote{questa eventualità non dovrebbe mai verificarsi,
+  almeno fintanto che la funzione \func{getaddrinfo} lavora correttamente.}
 
 Per ciascuno delle due possibili famiglie di indirizzi si estraggono le
 informazioni che poi verranno stampate alla fine del ciclo (\texttt{\small
@@ -1524,7 +1526,7 @@ puntatore al campo contenente l'indirizzo IP nella struttura puntata dal campo
 
 Una volta estratte dalla struttura \struct{addrinfo} tutte le informazioni
 relative alla risoluzione richiesta e stampati i relativi valori, l'ultimo
-passo è (\texttt{\small 34}) estrarre da \var{ai\_next} l'indirizzo della
+passo (\texttt{\small 34}) è di estrarre da \var{ai\_next} l'indirizzo della
 eventuale successiva struttura presente nella lista e ripetere il ciclo, fin
 tanto che, completata la scansione, questo avrà un valore nullo e si potrà
 terminare (\texttt{\small 36}) il programma.
@@ -1577,6 +1579,86 @@ si copiano anche tutti i dati presenti agli indirizzi contenuti nella
 struttura \struct{addrinfo}, perché una volta disallocati i dati con
 \func{freeaddrinfo} questi non sarebbero più disponibili. 
 
+Anche la nuova intefaccia definita da POSIX prevede una nuova funzione per
+eseguire la risoluzione inversa e determinare nomi di servizi e di dominio
+dati i rispettivi valori numerici. La funzione che sostituisce le varie
+\func{gethostbyname}, \func{geipnodebyname} e \func{getservname} è
+\funcd{getnameinfo}, ed il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/socket.h}
+  \headdecl{netdb.h}
+
+  \funcdecl{int getnameinfo(const struct sockaddr *sa, socklen\_t salen, char
+    *host, size\_t hostlen, char *serv, size\_t servlen, int flags)}
+
+  Risolve il contenuto di una struttura degli indirizzi in maniera
+  indipendente dal protocollo.
+
+  \bodydesc{La funzione restituisce 0 in caso di successo e un codice di
+    errore diverso da zero altrimenti.}
+\end{functions}
+
+La principale caratteristica di \func{getnameinfo} è che la funzione è in
+grado di eseguire una risoluzione inversa in maniera indipendente dal
+protocollo; il suo primo argomento \param{sa} infatti è il puntatore ad una
+struttura degli indirizzi generica, che può contenere sia indirizzi IPv4 che
+IPv6, la cui dimensione deve comunque essere specificata con l'argomento
+\param{salen}. 
+
+I risultati della funzione saranno restituiti nelle due stringhe puntate da
+\param{host} e \param{serv}, che dovranno essere state precedentemente
+allocate per una lunghezza massima che deve essere specificata con gli altri
+due argomenti \param{hostlen} e \param{servlen}. Si può, quando non si è
+interessati ad uno dei due, passare il valore \const{NULL} come argomento,
+così che la corrispondente informazione non verrà richiesta. Infine l'ultimo
+argomento \param{flags} è una maschera binaria i cui bit consentono di
+impostare le modalità con cui viene eseguita la ricerca, e deve essere
+specificato attraverso l'OR aritmetico dei valori illustrati in
+tab.~\ref{tab:getnameinfo_flags}.
+
+\begin{table}[!htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Costante} & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{NI\_NOFQDN}     & richiede che venga restituita solo il nome della
+                             macchina all'interno del dominio al posto del
+                             nome completo (FQDN).\\
+    \const{NI\_NUMERICHOST}& richiede che venga restituita la forma numerica
+                             dell'indirizzo (questo succede sempre se il nome
+                             non può essere ottenuto).\\ 
+    \const{NI\_NAMEREQD}   & richiede la restituzione di un errore se il nome
+                             non può essere risolto.\\
+    \const{NI\_NUMERICSERV}& richiede che il servizio venga restituito in
+                             forma numerica (attraverso il numero di porta).\\
+    \const{NI\_DGRAM}      & richiede che venga restituito il nome del
+                             servizio su UDP invece che quello su TCP per quei
+                             pichi servizi (porte 512-214) che soni diversi
+                             nei due protocolli.\\
+    \hline
+  \end{tabular}
+  \caption{Costanti associate ai bit dell'argomento \param{flags} della  
+    funzione \func{getnameinfo}.} 
+  \label{tab:getnameinfo_flags}
+\end{table}
+
+La funzione ritorna zero in caso di successo, e scrive i propri risultati agli
+indirizzi indicati dagli argomenti \param{host} e \param{serv} come stringhe
+terminate dal carattere NUL, a meno che queste non debbano essere troncate
+qualora la loro dimensione ecceda quelle specificate dagli argomenti
+\param{hostlen} e \param{servlen}. Sono comunque definite le due costanti
+\const{NI\_MAXHOST} e \const{NI\_MAXSERV}\footnote{le due costanti sono
+  definite in \file{netdb.h} ed hanno rispettivamente il valore 1024 e 12.}
+che possono essere utilizzate come limiti massimi.  In caso di errore viene
+restituito invece un codice che assume gli stessi valori illustrati in
+tab.~\ref{tab:addrinfo_error_code}.
+
+A questo punto possiamo fornire degli esempi di utilizzo diretto della nuova
+interfaccia, adottandola per rendere i nostri client 
+
 
 \section{Le opzioni dei socket}
 \label{sec:TCP_sock_options}
@@ -1585,7 +1667,7 @@ Finora abbiamo trattato i socket nel loro comportamento pi
 possibile attivare alcune modalità diverse di funzionamento degli stessi
 
 Dato che la maggior parte delle opzioni dei socket sono relative ai socket
-TCP, ed hanno poi significato analogo quando usate con altri socket, abbiamo
+ TCP, ed hanno poi significato analogo quando usate con altri socket, abbiamo
 preferito trattare l'argomento in generale in questa sezione piuttosto che nel
 capitolo dedicato alla trattazione generica dei socket.
 
diff --git a/sources/SockAddr.c b/sources/SockAddr.c
new file mode 100644 (file)
index 0000000..9a585eb
--- /dev/null
@@ -0,0 +1,70 @@
+/* SockAddr.c
+ * 
+ * Copyright (C) 2004 Simone Piccardi
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/***************************************************************
+ *
+ * File SockAddr.c 
+ * Routines for socket address resolution. 
+ *
+ *
+ * Author: S. Piccardi
+ *
+ * $Id$
+ *
+ ***************************************************************/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>          /* standard I/O functions */
+#include <signal.h>         /* signal handling declarations */
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>     /* socket function and declaration */
+#include <netdb.h>          /* resolver functions */
+
+
+#include "macros.h"
+/* *************************************************************************
+ *
+ *  Functions for socket address automatic resolution
+ *
+ * ************************************************************************* */
+/*
+ * Function tcp_socket
+ * Create and attach a SysV shared memory segment to the current process.
+ *
+ * First call get a shared memory segment with KEY key access and size SIZE,
+ * by creating it with R/W privilege for the user (this is the meaning of
+ * the ored flags). The function return an identifier shmid used for any 
+ * further reference to the shared memory segment. 
+ * Second call attach the shared memory segment to this process and return a
+ * pointer to it (of void * type). 
+ * Then initialize shared memory to the given value
+ *
+ * Input:  an host name
+ *         a service name
+ * Return: the IP address of the host in a sockaddr structure
+ */
+int tcp_addr(char * address, char * service, struct sockaddr * sa) 
+{
+    struct addrinfo hints;
+    
+
+    /* OK, exit */
+    return 0;
+}
index 93083b3..089bd67 100644 (file)
  *
  * Program TCP_echo_first.c (former ElemEchoTCPClient)
  * Simple TCP client for echo service (port 7)
+ * First version, broken in many ways, that will be corrected later
  *
  * Author: Simone Piccardi
  * Jun. 2001
  *
  * Usage: echo -h give all info's
  *
- * $Id: TCP_echo_first.c,v 1.2 2003/07/27 23:41:04 piccardi Exp $
+ * $Id$
  *
  ****************************************************************/
 /* 
diff --git a/sources/TCP_echo_fourth.c b/sources/TCP_echo_fourth.c
new file mode 100644 (file)
index 0000000..691911e
--- /dev/null
@@ -0,0 +1,189 @@
+/* TCP_echo.c
+ * 
+ * Copyright (C) 2001-2003 Simone Piccardi
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/****************************************************************
+ *
+ * Program TCP_echo.c
+ * Simple TCP client for echo service (port 7)
+ *
+ * Author: Simone Piccardi
+ * Jun. 2001
+ *
+ * Usage: echo -h give all info's
+ *
+ * $Id: TCP_echo.c,v 1.11 2003/10/20 22:44:16 piccardi Exp $
+ *
+ ****************************************************************/
+/* 
+ * Include needed headers
+ */
+#include <sys/types.h>   /* predefined types */
+#include <unistd.h>      /* include unix standard library */
+#include <arpa/inet.h>   /* IP addresses conversion utiliites */
+#include <sys/socket.h>  /* socket library */
+#include <stdio.h>      /* include standard I/O library */
+#include <errno.h>      /* include error codes */
+#include <string.h>     /* include erroro strings definitions */
+
+#include "macros.h"
+
+#define MAXLINE 256
+void usage(void);
+void ClientEcho(FILE * filein, int socket);
+void SigTERM_hand(int sig);
+
+/* Program begin */
+int main(int argc, char *argv[])
+{
+/* 
+ * Variables definition  
+ */
+    int sock, i;
+    int reset = 0;
+    struct sockaddr_in serv_add;
+    struct linger ling;
+    /*
+     * Input section: decode parameters passed in the calling 
+     * Use getopt function
+     */
+    opterr = 0;         /* don't want writing to stderr */
+    while ( (i = getopt(argc, argv, "hr")) != -1) {
+       switch (i) {
+       /* 
+        * Handling options 
+        */ 
+       case 'h':  
+           printf("Wrong -h option use\n");
+           usage();
+           return(1);
+           break;
+       case 'r':
+           reset = 1;
+           break;
+       case '?':   /* unrecognized options */
+           printf("Unrecognized options -%c\n",optopt);
+           usage();
+       default:    /* should not reached */
+           usage();
+       }
+    }
+    /* ***********************************************************
+     * 
+     *          Options processing completed
+     *
+     *               Main code beginning
+     * 
+     * ***********************************************************/
+    /* create socket */
+    if ( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+       perror("Socket creation error");
+       return 1;
+    }
+    /* initialize address */
+    memset((void *) &serv_add, 0, sizeof(serv_add)); /* clear server address */
+    serv_add.sin_family = AF_INET;                   /* address type is INET */
+    serv_add.sin_port = htons(7);                    /* echo port is 7 */
+    /* build address using inet_pton */
+    if ( (inet_pton(AF_INET, argv[optind], &serv_add.sin_addr)) <= 0) {
+       perror("Address creation error");
+       return 1;
+    }
+    /* extablish connection */
+    if (connect(sock, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) {
+       perror("Connection error");
+       return 1;
+    }
+    /* check if resetting on close is required */
+    if (reset) {
+       printf("Setting reset on close \n");
+       ling.l_onoff = 1;
+       ling.l_linger = 0;      
+       if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling))) {
+           perror("Cannot set linger");
+           exit(1);
+       }
+    }
+    /* do read/write operations */
+    ClientEcho(stdin, sock);
+    /* normal exit */
+    return 0;
+}
+/*
+ * routine to print usage info and exit 
+ */
+void usage(void) {
+    printf("Take daytime from a remote host \n");
+    printf("Usage:\n");
+    printf("  daytime [-h] [-v] [host in dotted decimal form] \n");
+//    printf("  -v        set verbosity on\n");
+    printf("  -r          require reset on closing\n");
+    printf("  -h          print this help\n");
+    exit(1);
+}
+
+void ClientEcho(FILE * filein, int socket) 
+{
+    char sendbuff[MAXLINE+1], recvbuff[MAXLINE+1];
+    int nread, nwrite; 
+    int maxfd;
+    fd_set fset;
+    int eof = 0;
+    /* initialize file descriptor set */
+    FD_ZERO(&fset);
+    maxfd = max(fileno(filein), socket) + 1;
+    while (1) {
+       FD_SET(socket, &fset);         /* set for the socket */
+       if (eof == 0) {
+           FD_SET(fileno(filein), &fset); /* set for the standard input */
+       }
+       select(maxfd, &fset, NULL, NULL, NULL); /* wait for read ready */
+       if (FD_ISSET(fileno(filein), &fset)) {  /* if ready on stdin */
+           if (fgets(sendbuff, MAXLINE, filein) == NULL) { /* if no input */
+               eof = 1;               /* EOF on input */
+               shutdown(socket, SHUT_WR);      /* close write half */
+               FD_CLR(fileno(filein), &fset);  /* no more interest on stdin */
+           } else {                   /* else we have to write to socket */
+               nwrite = FullWrite(socket, sendbuff, strlen(sendbuff)); 
+               if (nwrite < 0) {      /* on error stop */
+                   printf("Errore in scrittura: %s", strerror(errno));
+                   return;
+               }
+           }
+       }
+       if (FD_ISSET(socket, &fset)) { /* if ready on socket */ 
+           nread = read(socket, recvbuff, strlen(sendbuff)); /* do read */
+           if (nread < 0) {  /* error condition, stop client */
+               printf("Errore in lettura: %s\n", strerror(errno));
+               return;
+           }
+           if (nread == 0) { /* server closed connection, stop */
+               if (eof == 1) {
+                   return;
+               } else {
+                   printf("EOF prematuro sul socket\n");
+                   return;
+               }
+           }
+           recvbuff[nread] = 0;   /* else read is ok, write on stdout */
+           if (fputs(recvbuff, stdout) == EOF) {
+               perror("Errore in scrittura su terminale");
+               return;
+           }
+       }
+    }
+}
index fcf5a4f..5f0a92e 100644 (file)
@@ -1,4 +1,4 @@
-/* TCP_echo.c
+/* TCP_echo_second.c
  * 
  * Copyright (C) 2001-2003 Simone Piccardi
  * 
  */
 /****************************************************************
  *
- * Program TCP_echo.c
+ * Program TCP_echo_second.c
  * Simple TCP client for echo service (port 7)
+ * This version handle server closing connection
  *
  * Author: Simone Piccardi
  * Jun. 2001
  *
  * Usage: echo -h give all info's
  *
- * $Id: TCP_echo_second.c,v 1.1 2003/10/18 16:30:23 piccardi Exp $
+ * $Id$
  *
  ****************************************************************/
 /* 
index 680e0e8..ee2fa94 100644 (file)
@@ -1,4 +1,4 @@
-/* TCP_echo.c
+/* TCP_echo_third.c
  * 
  * Copyright (C) 2001-2003 Simone Piccardi
  * 
  */
 /****************************************************************
  *
- * Program TCP_echo.c
+ * Program TCP_echo_third.c
  * Simple TCP client for echo service (port 7)
+ * This version use select
  *
  * Author: Simone Piccardi
  * Jun. 2001
  *
  * Usage: echo -h give all info's
  *
- * $Id: TCP_echo_third.c,v 1.1 2003/10/20 22:44:16 piccardi Exp $
+ * $Id$
  *
  ****************************************************************/
 /* 
index 8359d3f..332fc5f 100644 (file)
@@ -1733,7 +1733,7 @@ utilizzato dallo stesso; il suo prototipo 
 \end{prototype}
 
 La funzione restituisce il tempo in tick, quindi se si vuole il tempo in
-secondi occorre moltiplicare il risultato per la costante
+secondi occorre dividere il risultato per la costante
 \const{CLOCKS\_PER\_SEC}.\footnote{le \acr{glibc} seguono lo standard ANSI C,
   POSIX richiede che \const{CLOCKS\_PER\_SEC} sia definito pari a 1000000
   indipendentemente dalla risoluzione del timer di sistema.} In genere
index bc65ae9..b78321e 100644 (file)
@@ -2980,7 +2980,7 @@ caso di nuovo il client non 
 suppone che il programma server non venga terminato correttamente, ma si
 blocchi tutto senza la possibilità di avere l'emissione di un segmento FIN che
 segnala la terminazione della connessione. Di nuovo fintanto che la
-connessione non si riattiva )con il riavvio della macchina del server) il
+connessione non si riattiva (con il riavvio della macchina del server) il
 client non è in grado di fare altro che accettare dell'input e tentare di
 inviarlo. La differenza in questo caso è che non appena la connessione
 ridiventa attiva i dati verranno sì trasmessi, ma essendo state perse tutte le
@@ -3146,8 +3146,8 @@ Si 
 della nostra funzione \func{ClientEcho}, in grado di gestire correttamente
 l'intero flusso di dati fra client e server. Il codice completo del client,
 comprendente la gestione delle opzioni a riga di comando e le istruzioni per
-la creazione della connessione, si trova nel file \texttt{TCP\_echo.c},
-distribuito coi sorgenti allegati alla guida.
+la creazione della connessione, si trova nel file
+\texttt{TCP\_echo\_fourth.c}, distribuito coi sorgenti allegati alla guida.
 
 La nuova versione è molto simile alla precedente di
 fig.~\ref{fig:TCP_ClientEcho_third}; la prima differenza è l'introduzione