Completato server elementare.
authorSimone Piccardi <piccardi@gnulinux.it>
Wed, 4 Apr 2001 23:09:57 +0000 (23:09 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Wed, 4 Apr 2001 23:09:57 +0000 (23:09 +0000)
files.tex
main.tex
network.tex
sources/SimpleDaytimeTCPServer.c [new file with mode: 0644]

index 64482d02e46f3a3a3198ab484d5436bfe058b85a..a9f253b42f83c52eb13068c24339401fcfa4cf13 100644 (file)
--- a/files.tex
+++ b/files.tex
@@ -617,7 +617,7 @@ nell'header file \texttt{unistd.h}.
   \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di
     già.
   \item \texttt{EMLINK} Ci sono troppi link al file \texttt{oldname} (il
   \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di
     già.
   \item \texttt{EMLINK} Ci sono troppi link al file \texttt{oldname} (il
-    numero massimo è specificato dalla variabile \texttt{LINK_MAX}, vedi
+    numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi
     \ref{sec:sys_limits}.
   \item \texttt{ENOSPC} La directory in cui si vuole creare il link è piena e
     non può essere .
     \ref{sec:sys_limits}.
   \item \texttt{ENOSPC} La directory in cui si vuole creare il link è piena e
     non può essere .
index da2fd9759030cb7b36008c5abd59453223a9f300..569f7086acebb9424631e2086f6f237199fdbfd5 100644 (file)
--- a/main.tex
+++ b/main.tex
@@ -28,6 +28,8 @@
 
 %\includeonly{macro,pref,intro,fdl}
 
 
 %\includeonly{macro,pref,intro,fdl}
 
+
+
 \title{Guida alla Programmazione in Linux.}
 
 \author{Simone Piccardi}
 \title{Guida alla Programmazione in Linux.}
 
 \author{Simone Piccardi}
@@ -56,6 +58,7 @@
 \end{quote}
 \clearemptydoublepage
 
 \end{quote}
 \clearemptydoublepage
 
+
 \tableofcontents
 \clearemptydoublepage
 
 \tableofcontents
 \clearemptydoublepage
 
index 3a72f11f1f9649d6c536204bc30c94d8028afcb4..80d37ebad9a5bd76f3290f8f92c1969a16bd6618 100644 (file)
@@ -1,18 +1,20 @@
-\chapter{Introduzione alla rete}
+\chapter{Introduzione alla programmazione di rete}
 \label{cha:network}
 
 In questo capitolo sarà fatta un'introduzione ai contetti generali che servono
 \label{cha:network}
 
 In questo capitolo sarà fatta un'introduzione ai contetti generali che servono
-come prerequisiti per capire la programmazione di rete ed esamineremo a grandi
-linee i protocolli di rete e come questi sono organizzati e interagiscono.
+come prerequisiti per capire la programmazione di rete, partiremo con due
+semplici esempi per poi passare ad un esame a grandi linee dei protocolli di
+rete e di come questi sono organizzati e interagiscono.
 
 In particolare, avendo assunto l'ottica di un'introduzione mirata alla
 
 In particolare, avendo assunto l'ottica di un'introduzione mirata alla
-programmazione, ci concentreremo sul protocollo più diffuso che è quello che
-sta alla base di internet, ed in particolare sulle parti più importanti ai
-fini della programmazione. 
+programmazione, ci concentreremo sul protocollo più diffuso, TCP/IP, che è
+quello che sta alla base di internet, ed in particolare prenderemo in esame in
+questa introduzione i concetti più importanti da conoscere ai fini della
+programmazione.
 
 
 \section{Il modello client-server}
 
 
 \section{Il modello client-server}
-\label{sec:net_cliserv}.
+\label{sec:net_cliserv}
 
 La differenza principale fra un'applicazione di rete e un programma normale è
 che quest'ultima per definizione concerne la comunicazione fra ``processi''
 
 La differenza principale fra un'applicazione di rete e un programma normale è
 che quest'ultima per definizione concerne la comunicazione fra ``processi''
@@ -33,8 +35,8 @@ servizio che viene fornito tramite la rete, ma il modello 
 generale anche per programmi che non fanno necessariamente uso della rete,
 come il sistema a finestre.
 
 generale anche per programmi che non fanno necessariamente uso della rete,
 come il sistema a finestre.
 
-Normalmente si dividono i server in due categorie principali,
-\textit{concorrenti} e \textit{iterativi}, sulla base del loro comportamento.
+Normalmente si dividono i server in due categorie principali, e vengono detti
+\textit{concorrenti} o \textit{iterativi}, sulla base del loro comportamento.
 
 Un server iterativo risponde alla richiesta inviando i dati e resta occupato
 (non rispondendo ad ulteriori richieste) fintanto che non ha concluso la
 
 Un server iterativo risponde alla richiesta inviando i dati e resta occupato
 (non rispondendo ad ulteriori richieste) fintanto che non ha concluso la
@@ -44,20 +46,20 @@ disponibile.
 Un server concorrente al momento di trattare la richiesta crea un processo
 figlio incaricato di fornire i servizi richiesti, per poi porsi in attesa di
 ulteriori richieste. In questo modo più richieste possono essere soddisfatte
 Un server concorrente al momento di trattare la richiesta crea un processo
 figlio incaricato di fornire i servizi richiesti, per poi porsi in attesa di
 ulteriori richieste. In questo modo più richieste possono essere soddisfatte
-contemporaneamente, una volta che il processo figlio ha concluso il suo lavoro
+contemporaneamente; una volta che il processo figlio ha concluso il suo lavoro
 viene terminato, mentre il server originale resta sempre attivo.
 
 
 \subsection{Un primo esempio di client}
 \label{sec:net_cli_sample}
 
 viene terminato, mentre il server originale resta sempre attivo.
 
 
 \subsection{Un primo esempio di client}
 \label{sec:net_cli_sample}
 
-Per evitare di rendere l'esposizione dei concetti generali puramente teorica
-iniziamo con il mostrare un semplice esempio di client TCP.  In \nfig è
-riportata la sezione principale del codice del nostro client elementare per il
-servizio \textit{daytime}, un servizio standard che restituisce l'ora locale
-della macchina a cui si effettua la richesta.
+Per evitare di rendere l'esposizione dei concetti generali sulla rete
+puramente teorica iniziamo con il mostrare un semplice esempio di client TCP.
+In \nfig\ è riportata la sezione principale del codice del nostro client
+elementare per il servizio \textit{daytime}, un servizio standard che
+restituisce l'ora locale della macchina a cui si effettua la richesta.
 
 
-\begin{figure}[htbp]
+\begin{figure}[!htbp]
   \footnotesize
   \begin{lstlisting}{}
 #include <sys/types.h>   /* predefined types */
   \footnotesize
   \begin{lstlisting}{}
 #include <sys/types.h>   /* predefined types */
@@ -109,62 +111,193 @@ int main(int argc, char *argv[])
     return 0;
 }
   \end{lstlisting}
     return 0;
 }
   \end{lstlisting}
-  \caption{Esempio di codice di un semplice client per il servizio daytime.}
+  \caption{Esempio di codice di un client elementare per il servizio daytime.}
   \label{fig:net_cli_code}
 \end{figure}
 
   \label{fig:net_cli_code}
 \end{figure}
 
-
 Scopo di questo esempio è fornire un primo approccio alla programmazione di
 rete, per questo motivo non ci dilungheremo nel trattare il significato dei
 termini o il funzionamento delle varie funzioni utilizzate. Tutto questo sarà
 esaminato in dettaglio nel seguito, per cui qui ci limiteremo a citarli senza
 ulteriori spiegazioni.
 
 Scopo di questo esempio è fornire un primo approccio alla programmazione di
 rete, per questo motivo non ci dilungheremo nel trattare il significato dei
 termini o il funzionamento delle varie funzioni utilizzate. Tutto questo sarà
 esaminato in dettaglio nel seguito, per cui qui ci limiteremo a citarli senza
 ulteriori spiegazioni.
 
-Il listato completo del programma (che comprende il trattamento delle opzioni
-e una funzione per stampare un messaggio di aiuto) è allegato alla guida nella
-sezione dei codici sorgente e può essere compilato su una qualunque macchina
-linux.
+Il sorgente completo del programma (\texttt{SimpleDaytimeTCPClient.c}, che
+comprende il trattamento delle opzioni e una funzione per stampare un
+messaggio di aiuto) è allegato alla guida nella sezione dei codici sorgente e
+può essere compilato su una qualunque macchina linux.
 
 Il programma anzitutto include gli header necessari (\texttt{\small 1--5});
 
 Il programma anzitutto include gli header necessari (\texttt{\small 1--5});
-dopo la dichiarazione delle variabili (\texttt{\small 9--12}), si è omessa
+dopo la dichiarazione delle variabili (\texttt{\small 9--12}) si è omessa
 tutta la parte relativa al trattamento degli argomenti passati dalla linea di
 tutta la parte relativa al trattamento degli argomenti passati dalla linea di
-comando effettuata con le apposite routines illustrate in
-\ref{cha:parameter_options}.
+comando (effettuata con le apposite routines illustrate in
+\ref{cha:parameter_options}).
 
 
-Il primo passo (\texttt{\small 14--18}è creare un \textit{socket} internet
-(\texttt{AF\_INET}), di tipo TCP \texttt{SOCK\_STREAM}), la funzione ritorna
-un descrittore, analogo a quello dei file, che viene usato per identificare il
-socket in tutte le chiamate successive. Nel caso la chiamata fallisca si
-stampa un errore con la relativa routine e si esce.
+Il primo passo (\texttt{\small 14--18}) è creare un \textit{socket} IPv4
+(\texttt{AF\_INET}), di tipo TCP \texttt{SOCK\_STREAM} (in sostanza un canale
+di comunicazione attraverso internet, questi termini verranno spiegati con
+precisione più avanti). La funzione \texttt{socket} ritorna un descrittore,
+analogo a quello dei file, che viene usato per identificare il socket in tutte
+le chiamate successive. Nel caso la chiamata fallisca si stampa un errore con
+la relativa routine e si esce.
 
 Il passo seguente (\texttt{\small 19--27}) è quello di costruire una apposita
 struttura \texttt{sockaddr\_in} in cui sarà inserito l'indirizzo del server ed
 il numero della porta del servizio. Il primo passo è inizializzare tutto a
 
 Il passo seguente (\texttt{\small 19--27}) è quello di costruire una apposita
 struttura \texttt{sockaddr\_in} in cui sarà inserito l'indirizzo del server ed
 il numero della porta del servizio. Il primo passo è inizializzare tutto a
-zero, poi si setta il tipo di protocollo e la porta (usando la funzione
-\texttt{htons} per convertire il formato dell'intero a quello usato nella
-rete), infine si utilizza la funzione \texttt{inet\_pton} per convertire
-l'indirizzo numerico passato dalla linea di comando.
-
-Usando la funzione \texttt{connect} (\texttt{\small 28--32}) si provvede poi a
-stabilire la connessione con il server. Un valore negativo 
+zero, per poi inserire il tipo di protocollo e la porta (usando per
+quest'ultima la funzione \texttt{htons} per convertire il formato dell'intero
+usato dal computer a quello usato nella rete), infine si utilizza la funzione
+\texttt{inet\_pton} per convertire l'indirizzo numerico passato dalla linea di
+comando.
+
+Usando la funzione \texttt{connect} sul socket creato in precedenza
+(\texttt{\small 28--32}) si provvede poi a stabilire la connessione con il
+server specificato dall'indirizzo immesso nella struttura possata come secondo
+argomento, il terzo argomento è la dimensione di detta struttura. Dato che
+esistono diversi tipi di socket, si è dovuto effettuare un cast della
+struttura inizializzata in precedenza, che è specifica per i socket IPv4.  Un
+valore di ritorno negativo implica il fallimento della connessione.
+
+Completata con successo la connessione il passo successivo (\texttt{\small
+  34--40}) è leggere la data dal socket; il server invierà sempre una stringa
+di 26 caratteri della forma \verb|Wed Apr 4 00:53:00 2001\r\n|, che viene
+letta dalla funzione \texttt{read} e scritta su \texttt{stdout}.
+
+Dato il funzionamento di TCP la risposta potrà tornare in un unico pacchetto
+di 26 byte (come avverrà senz'altro nel caso in questione) ma potrebbe anche
+arrivare in 26 pacchetti di un byte.  Per questo nel caso generale non si può
+mai assumere che tutti i dati arrivino con una singola lettura, pertanto
+quest'ultima deve essere effettuata in un loop in cui si continui a leggere
+fintanto che la funzione \texttt{read} non ritorni uno zero (che significa che
+l'altro capo ha chiuso la connessione) o un numero minore di zero (che
+significa un errore nella connessione).
+
+Si noti come in questo caso la fine dei dati sia specificata dal server che
+chiude la connessione; questa è una delle tecniche possibili (è quella usata
+pure dal protocollo HTTP), ma ce ne possono essere altre, ad esempio FTP marca
+la conclusione di un blocco di dati con la sequenza ASCII \verb|\r\n|
+(carriage return e line feed), mentre il DNS mette la lunghezza in testa ad
+ogni blocco che trasmette. Il punto essenziale è che TCP non provvede nessuna
+indicazione che permetta di marcare dei blocchi di dati, per cui se questo è
+necessario deve provvedere il programma stesso.
 
 \subsection{Un primo esempio di server}
 \label{sec:net_serv_sample}
 
 
 \subsection{Un primo esempio di server}
 \label{sec:net_serv_sample}
 
-Dopo aver visto il client facciamo vedere adesso anche il corrispettivo
-server, in questo modo sarà possibile fare delle prove 
+Dopo aver illustrato il client daremo anche un esempio di un server
+elementare, in grado di rispondere al precedente client. Il listato è
+nuovamente mostrato in \nfig, il sorgente completo
+(\texttt{SimpleDaytimeTCPServer.c}) è allegato insieme agli altri file nella
+directory \texttt{sources}.
 
 
-\begin{figure}[htbp]
-  \begin{center}
-    \begin{verbatim}
+\begin{figure}[!htbp]
+  \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>
+#define MAXLINE 80
+#define BACKLOG 10
+int main(int argc, char *argv[])
+{
+/* 
+ * Variables definition  
+ */
+    int list_fd, conn_fd;
+    int i;
+    struct sockaddr_in serv_add;
+    char buffer[MAXLINE];
+    time_t timeval;
 
 
+    ...
 
 
-    \end{verbatim}
-    \caption{Esempio di codice di un semplice server per il servizio daytime.}
-    \label{fig:net_serv_code}
-  \end{center}
+    /* 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 *) NULL, NULL)) <0 ) {
+            perror("accept error");
+            exit(-1);
+        }
+        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);
+        }
+        close(conn_fd);
+    }
+    /* normal exit */
+    exit(0);
+}
+  \end{lstlisting}
+  \caption{Esempio di codice di un semplice server per il servizio daytime.}
+  \label{fig:net_serv_code}
 \end{figure}
 
 \end{figure}
 
+Come per il client si includono gli header necessari a cui è aggiunto quello
+per trattare i tempi, e si definiscono alcune costanti e le variabili
+necessarie in seguito (\texttt{\small 1--18}), come nel caso precedente si
+sono omesse le parti relative al trattamento delle opzioni da riga di comando.
+
+La creazione del socket (\texttt{\small 22--26}) è analoga al caso precedente,
+come pure l'inizializzazione della struttura \texttt{sockaddr\_in}, anche in
+questo caso si usa la porta standard del servizio daytime, ma come indirizzo
+IP si il valore predefinito \texttt{INET\_ANY} che corrisponde ad un indirizzo
+generico (\texttt{\small 27--31}).
+
+Si effettua poi (\texttt{\small 32--36}) la chiamata alla funzione
+\texttt{bind} che permette di associare la precedente struttura al socket, in
+modo che quest'ultimo possa essere usato per accettare connessioni su una
+qualunque delle interfacce di rete locali.
+
+Il passo successivo (\texttt{\small 37--41}) è mettere ``in ascolto'' il
+socket, questo viene effettuato con la funzione \texttt{listen} che dice al
+kernel di accettare connessioni per il socket specificato, la funzione indica
+inoltre, con il secondo parametro, il numero massimo di connessioni che il
+kernel accetterà di mettere in coda per il suddetto socket.
+
+Questa ultima chiamata completa la preparazione del socket per l'ascolto (che
+viene chiamato anche \textit{listening descriptor}) a questo punto il processo
+è mandato in sleep (\texttt{\small 44--47}) con la successiva chiamata alla
+funzione \texttt{accept}, fin quando non arriva e viene accettata una
+connessione da un client.
+
+Quando questo avviene \texttt{accept} ritorna un secondo descrittore di
+socket, che viene chiamato \textit{connected descriptor} che è quello che
+viene usato dalla successiva chiamata alla \texttt{write} per scrivere la
+risposta al client, una volta che si è opportunamente (\texttt{\small 48--49})
+costruita la stringa con la data da trasmettere. Completata la trasmissione il
+nuovo socket viene chiuso (\texttt{\small 54}).
+Il tutto è inserito in un loop infinito (\texttt{\small 42--55}) in modo da
+poter ripetere l'invio della data ad una successiva connessione.
+
+È impostante notare che questo server è estremamente elementare, infatti a
+parte il fatto di essere dipendente da IPv4, esso è in grado di servire solo
+un client alla volta, è cioè un \textsl{server iterativo}, inoltre esso è
+scritto per essere lanciato da linea di comando, se lo si volesse utilizzare
+come demone di sistema (che è in esecuzione anche quando non c'è nessuna shell
+attiva), occorrerebbero delle opportune modifiche.
 
 \section{I protocolli di rete}
 \label{sec:net_protocols}
 
 \section{I protocolli di rete}
 \label{sec:net_protocols}
@@ -174,7 +307,7 @@ eterogeneo di mezzi di comunicazione che vanno dal cavo telefonico, alla fibra
 ottica, alle comunicazioni via satellite; per rendere possibile la
 comunicazione attraverso un così variegato insieme di mezzi sono stati
 adottati una serie di protocolli, il più famoso dei quali, quello alla base
 ottica, alle comunicazioni via satellite; per rendere possibile la
 comunicazione attraverso un così variegato insieme di mezzi sono stati
 adottati una serie di protocolli, il più famoso dei quali, quello alla base
-del funzionamento di internet, è il cosiddetto TCP/IP.
+del funzionamento di internet, è il protocollo TCP/IP.
 
 \subsection{Il modello ISO/OSI}
 \label{sec:net_iso_osi}
 
 \subsection{Il modello ISO/OSI}
 \label{sec:net_iso_osi}
@@ -219,7 +352,7 @@ della Difesa Americano.
 \label{sec:net_tcpip_overview}
 
 Così come ISO/OSI anche TCP/IP è stato strutturato in livelli (riassunti in
 \label{sec:net_tcpip_overview}
 
 Così come ISO/OSI anche TCP/IP è stato strutturato in livelli (riassunti in
-\ntab); un confronto fra i due è riportato in \nfig dove viene evidenziata
+\ntab); un confronto fra i due è riportato in \nfig\ dove viene evidenziata
 anche la corrispondenza fra i rispettivi livelli (che comunque è
 approssimativa) e su come essi vanno ad inserirsi all'interno del sistema
 operativo rispetto alla divisione fra user space e kernel space spiegata in
 anche la corrispondenza fra i rispettivi livelli (che comunque è
 approssimativa) e su come essi vanno ad inserirsi all'interno del sistema
 operativo rispetto alla divisione fra user space e kernel space spiegata in
@@ -354,7 +487,7 @@ spiegazioni.
 \subsection{Il quadro generale}
 
 Benché si parli di TCP/IP questa famiglia di protocolli è composta anche da
 \subsection{Il quadro generale}
 
 Benché si parli di TCP/IP questa famiglia di protocolli è composta anche da
-altri membri. In \nfig si è riportato una figura di quadro che mostra un
+altri membri. In \nfig\ si è riportato una figura di quadro che mostra un
 panorama sull'intera famiglia, e di come i vari protocolli vengano usati dalle
 applicazioni.
 
 panorama sull'intera famiglia, e di come i vari protocolli vengano usati dalle
 applicazioni.
 
diff --git a/sources/SimpleDaytimeTCPServer.c b/sources/SimpleDaytimeTCPServer.c
new file mode 100644 (file)
index 0000000..fdf99ec
--- /dev/null
@@ -0,0 +1,114 @@
+/****************************************************************
+ *
+ * Program daytime_tcp_server.c: 
+ * Simple TCP server for daytime service (port 13)
+ *
+ * Author: Simone Piccardi
+ * Apr. 2001
+ *
+ * Usage: daytimed
+ *
+ * $Id: SimpleDaytimeTCPServer.c,v 1.1 2001/04/04 23:09:57 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;
+    char buffer[MAXLINE];
+    time_t timeval;
+    /*
+     * Input section: decode parameters passed in the calling 
+     * Use getopt function
+     */
+    opterr = 0;         /* don't want writing to stderr */
+    while ( (i = getopt(argc, argv, "h")) != -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();
+       default:    /* should not reached */
+           usage();
+       }
+    }
+    /* ***********************************************************
+     * 
+     *          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 *) NULL, NULL)) <0 ) {
+           perror("accept error");
+           exit(-1);
+       }
+       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);
+       }
+       close(conn_fd);
+    }
+
+    /* normal exit */
+    exit(0);
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+    printf("Simple daytime server\n");
+    printf("Usage:\n");
+    printf("  daytimed [-h] \n");
+    printf("  -h          print this help\n");
+    exit(1);
+}