Aggiunta versione concorrente del server daytime. Iniziata la relativa
authorSimone Piccardi <piccardi@gnulinux.it>
Sat, 19 May 2001 20:47:03 +0000 (20:47 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sat, 19 May 2001 20:47:03 +0000 (20:47 +0000)
spiegazione.

elemtcp.tex
main.tex
sources/ElemDaytimeTCPCuncServ.c [new file with mode: 0644]
sources/SimpleDaytimeTCPServer.c

index fcb3b32ec8c98f279bb6acf51b05cb0974e90931..fd2d34a23c1951015357132c800a1c5a9e230356 100644 (file)
@@ -876,7 +876,7 @@ Storicamente il valore del parametro \texttt{backlog} era corrispondente al
 massimo valore della somma del numero di entrate possibili per ciascuna di
 dette code. Stevens riporta che BSD ha sempre applicato un fattore di 1.5 al
 valore, e provvede una tabella con i risultati ottenuti con vari kernel,
 massimo valore della somma del numero di entrate possibili per ciascuna di
 dette code. Stevens riporta che BSD ha sempre applicato un fattore di 1.5 al
 valore, e provvede una tabella con i risultati ottenuti con vari kernel,
-compreso linux 2.0, che mostrano le differenze fra diverse implementazioni.
+compreso linux 2.0, che mostrano le differenze fra diverse implementazioni. 
 
 Ma in linux il significato di questo valore è cambiato a partire dal kernel
 2.2 per prevenire l'attacco chiamato \texttt{syn flood}. Questo si basa
 
 Ma in linux il significato di questo valore è cambiato a partire dal kernel
 2.2 per prevenire l'attacco chiamato \texttt{syn flood}. Questo si basa
@@ -893,7 +893,9 @@ la \texttt{sysctl} o scrivendola direttamente in
 \texttt{/proc/sys/net/ipv4/tcp\_max\_syn\_backlog}. Quando si attiva la
 protezione dei syncookies però (con l'opzione da compilare nel kernel e da
 attivare usando \texttt{/proc/sys/net/ipv4/tcp\_syncookies}) questo valore
 \texttt{/proc/sys/net/ipv4/tcp\_max\_syn\_backlog}. Quando si attiva la
 protezione dei syncookies però (con l'opzione da compilare nel kernel e da
 attivare usando \texttt{/proc/sys/net/ipv4/tcp\_syncookies}) questo valore
-viene ignorato e non esiste più un valore massimo.
+viene ignorato e non esiste più un valore massimo.  In ogni caso in linux il
+valore di \texttt{backlog} viene troncato ad un massimo di \texttt{SOMAXCONN}
+se è superiore a detta constante (che di default vale 128).
 
 La scelta storica per il valore di questo parametro è di 5, e alcuni vecchi
 kernel non supportavano neanche valori superiori, ma la situazione corrente è
 
 La scelta storica per il valore di questo parametro è di 5, e alcuni vecchi
 kernel non supportavano neanche valori superiori, ma la situazione corrente è
@@ -904,11 +906,11 @@ conviene specificare questo valore con una costante (il cui cambiamento
 richiederebbe la ricompilazione del server) ma usare piuttosto una variabile
 di ambiente (vedi \secref{sec:xxx_env_var}).  Lo Stevens tratta accuratamente
 questo argomento, con esempi presi da casi reali su web server, ed in
 richiederebbe la ricompilazione del server) ma usare piuttosto una variabile
 di ambiente (vedi \secref{sec:xxx_env_var}).  Lo Stevens tratta accuratamente
 questo argomento, con esempi presi da casi reali su web server, ed in
-particolare evidenzia come non sia più vero che la ragione della coda è quella
-di gestire il caso in cui il server è occupato fra chiamate successive alla
-\texttt{accept} (per cui la coda più occupata sarebbe quella delle connessioni
-compeltate), ma è invece necessaria a gestire la presenza di un gran numero di
-SYN in attesa di completare il three-way handshake.
+particolare evidenzia come non sia più vero che il compito principale della
+coda sia quello di gestire il caso in cui il server è occupato fra chiamate
+successive alla \texttt{accept} (per cui la coda più occupata sarebbe quella
+delle connessioni compeltate), ma piuttosto quello di gestire la presenza di
+un gran numero di SYN in attesa di completare il three-way handshake.
 
 Come accennato nel caso del TCP se un SYN arriva con tutte le code piene, il
 pacchetto sarà ignorato. Questo viene fatto perché la condizione delle code
 
 Come accennato nel caso del TCP se un SYN arriva con tutte le code piene, il
 pacchetto sarà ignorato. Questo viene fatto perché la condizione delle code
@@ -981,7 +983,7 @@ E da chiarire che linux presenta un comportamento diverso nella gestione degli
 errori rispetto ad altre implementazioni dei socket BSD, infatti la funzione
 \texttt{accept} passa gli errori di rete pendenti sul nuovo socket come codici
 di errore per \texttt{accept}. Inoltre la funzione non fa ereditare ai nuovi
 errori rispetto ad altre implementazioni dei socket BSD, infatti la funzione
 \texttt{accept} passa gli errori di rete pendenti sul nuovo socket come codici
 di errore per \texttt{accept}. Inoltre la funzione non fa ereditare ai nuovi
-socket flag come \texttt{O_NONBLOCK}, che devono essere rispecificati volta
+socket flag come \texttt{O\_NONBLOCK}, che devono essere rispecificati volta
 volta, questo è un comportamento diverso rispetto a quanto accade con BSD e
 deve essere tenuto in conto per scrivere programmi portabili.
 
 volta, questo è un comportamento diverso rispetto a quanto accade con BSD e
 deve essere tenuto in conto per scrivere programmi portabili.
 
@@ -1021,4 +1023,87 @@ creato da \texttt{accept} viene chiuso dopo l'invio dei dati.
 \section{Un server concorrente su TCP}
 \label{sec:TCPel_cunc_serv}
 
 \section{Un server concorrente su TCP}
 \label{sec:TCPel_cunc_serv}
 
+Il server \texttt{daytime} dell'esempio in \secref{sec:net_cli_sample} è un
+tipico esempio di server iterativo, in cui viene servita una richiesta alla
+volta; in generale però, specie se il servizio è più complesso e comporta uno
+scambio di dati più sostanzioso di quello in questione, non è opportuno
+bloccare un server nel servizio di un client per volta; per questo si ricorre
+alle capacità di multitasking del sistema.
+
+Il modo più immediato per creare un server concorrente è allora quello di
+usare la funzione \texttt{fork} per far creare al server per ogni richiesta da
+parte di un client un processo figlio che si incarichi della gestione della
+comunicazione.
+
+Per illustrare questo meccanismo abbiamo allora riscritto il server
+\texttt{daytime} in forma concorrente, inserendo anche una opzione per la
+stampa degli indirizzi delle connessioni ricevute.
+
+In \nfig\ è mostrato un estratto del codice, in cui si sono tralasciate il
+trattamento delle opzioni e le parti rimaste invariate rispetto al precedente
+esempio. Al solito il sorgente completo del server
+\texttt{ElemDaytimeTCPCuncServ.c} è allegato nella directory dei sorgenti.
+
+\begin{figure}[!htb]
+  \footnotesize
+  \begin{lstlisting}{}
+#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 <time.h>
+
+int main(int argc, char *argv[])
+{
+    int list_fd, conn_fd;
+    int i;
+    struct sockaddr_in serv_add, client;
+    char buffer[MAXLINE];
+    socklen_t len;
+    time_t timeval;
+    pid_t pid;
+    int logging=0;
+     ...
+    /* write daytime to client */
+    while (1) {
+        if ( (conn_fd = accept(list_fd, (struct sockaddr *)&client, &len)) 
+             <0 ) {
+            perror("accept error");
+            exit(-1);
+        }
+        /* fork to handle connection */
+        if ( (pid = fork()) < 0 ){
+            perror("fork error");
+            exit(-1);
+        }
+        if (pid == 0) {                 /* child */
+            close(list_fd);
+            timeval = time(NULL);
+            snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&timeval));
+            if ( (write(conn_fd, buffer, strlen(buffer))) < 0 ) {
+                perror("write error");
+                exit(-1);
+            }
+            if (logging) {
+                inet_ntop(AF_INET, &client.sin_addr, buffer, sizeof(buffer));
+                printf("Request from host %s, port %d\n", buffer,
+                       ntohs(client.sin_port));
+            }
+            close(conn_fd);
+            exit(0);
+        } else {                        /* parent */
+            close(conn_fd);
+        }
+    }
+    /* normal exit, never reached */
+    exit(0);
+}
+  \end{lstlisting}
+  \caption{Esempio di codice di un server concorrente elementare per il 
+    servizio daytime.}
+  \label{fig:net_cli_code}
+\end{figure}
+
+Come si può vedere (\texttt{\small 21--25}) alla funzione \texttt{accept} 
 
 
index 097db57d8bb106682ad1e1f5e5fb69122ecc901a..55daeecf08ff81459e2212cf36a3b4345b6086da 100644 (file)
--- a/main.tex
+++ b/main.tex
@@ -1,4 +1,4 @@
-%% 
+%%
 %% GaPiL : Guida alla Programmazione in Linux
 %% 
 %% S. Piccardi Feb. 2001
 %% GaPiL : Guida alla Programmazione in Linux
 %% 
 %% S. Piccardi Feb. 2001
@@ -21,7 +21,7 @@
 \usepackage{color} 
 %
 % Setting page layout
 \usepackage{color} 
 %
 % Setting page layout
-% 
+%
 \oddsidemargin=0.5cm
 \evensidemargin=-0.5cm
 \textwidth=16cm
 \oddsidemargin=0.5cm
 \evensidemargin=-0.5cm
 \textwidth=16cm
diff --git a/sources/ElemDaytimeTCPCuncServ.c b/sources/ElemDaytimeTCPCuncServ.c
new file mode 100644 (file)
index 0000000..e6e9c49
--- /dev/null
@@ -0,0 +1,141 @@
+/****************************************************************
+ *
+ * Program ElemDaytimeTCPCuncServ.c 
+ * Elementary TCP cuncurrent server for daytime service (port 13)
+ *
+ * Author: Simone Piccardi
+ * May. 2001
+ *
+ * Usage: daytimed
+ *
+ * $Id: ElemDaytimeTCPCuncServ.c,v 1.1 2001/05/19 20:47:03 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 <time.h>
+
+#define MAXLINE 80
+#define BACKLOG 10
+/* Program begin */
+void usage(void);
+int main(int argc, char *argv[])
+{
+/* 
+ * Variables definition  
+ */
+    int list_fd, conn_fd;
+    int i;
+    struct sockaddr_in serv_add, client;
+    char buffer[MAXLINE];
+    socklen_t len;
+    time_t timeval;
+    pid_t pid;
+    int logging=0;
+    /*
+     * Input section: decode parameters passed in the calling 
+     * Use getopt function
+     */
+    opterr = 0;         /* don't want writing to stderr */
+    while ( (i = getopt(argc, argv, "hv")) != -1) {
+       switch (i) {
+       /* 
+        * Handling options 
+        */ 
+       case 'h':  
+           printf("Wrong -h option use\n");
+           usage();
+           return(0);
+           break;
+       case '?':   /* unrecognized options */
+           printf("Unrecognized options -%c\n",optopt);
+           usage();
+           return(0);
+           break;
+       case 'v':
+           logging = 1;
+           break;
+       default:    /* should not reached */
+           usage();
+           return(0);
+       }
+    }
+    /* ***********************************************************
+     * 
+     *          Options processing completed
+     *
+     *               Main code beginning
+     * 
+     * ***********************************************************/
+    /* create socket */
+    if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+       perror("Socket creation error");
+       exit(-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(13);                  /* daytime port is 13 */
+    serv_add.sin_addr.s_addr = htonl(INADDR_ANY);   /* connect from anywhere */
+    /* bind socket */
+    if (bind(list_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) {
+       perror("bind error");
+       exit(-1);
+    }
+    /* listen on socket */
+    if (listen(list_fd, BACKLOG) < 0 ) {
+       perror("listen error");
+       exit(-1);
+    }
+    /* write daytime to client */
+    while (1) {
+       if ( (conn_fd = accept(list_fd, (struct sockaddr *)&client, &len)) 
+            <0 ) {
+           perror("accept error");
+           exit(-1);
+       }
+       /* fork to handle connection */
+       if ( (pid = fork()) < 0 ){
+           perror("fork error");
+           exit(-1);
+       }
+       if (pid == 0) {                 /* child */
+           close(list_fd);
+           timeval = time(NULL);
+           snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&timeval));
+           if ( (write(conn_fd, buffer, strlen(buffer))) < 0 ) {
+               perror("write error");
+               exit(-1);
+           }
+           if (logging) {
+               inet_ntop(AF_INET, &client.sin_addr, buffer, sizeof(buffer));
+               printf("Request from host %s, port %d\n", buffer,
+                      ntohs(client.sin_port));
+           }
+           close(conn_fd);
+           exit(0);
+       } else {                        /* parent */
+           close(conn_fd);
+       }
+    }
+    /* normal exit, never reached */
+    exit(0);
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+    printf("Simple daytime server\n");
+    printf("Usage:\n");
+    printf("  daytimed [-hv] \n");
+    printf("  -h          print this help\n");
+    printf("  -v          print request source on stdout\n");
+    exit(1);
+}
+
index fdf99ec7ed944821a2d49e712b50832c5c6aeda4..9f6b9be36a4a79059be1896967af279b293e736d 100644 (file)
@@ -1,14 +1,14 @@
 /****************************************************************
  *
  * Program daytime_tcp_server.c: 
 /****************************************************************
  *
  * Program daytime_tcp_server.c: 
- * Simple TCP server for daytime service (port 13)
+ * Elementary TCP server for daytime service (port 13)
  *
  * Author: Simone Piccardi
  * Apr. 2001
  *
  * Usage: daytimed
  *
  *
  * Author: Simone Piccardi
  * Apr. 2001
  *
  * Usage: daytimed
  *
- * $Id: SimpleDaytimeTCPServer.c,v 1.1 2001/04/04 23:09:57 piccardi Exp $ 
+ * $Id: SimpleDaytimeTCPServer.c,v 1.2 2001/05/19 20:47:03 piccardi Exp $ 
  *
  ****************************************************************/
 /* 
  *
  ****************************************************************/
 /*