}
/* write daytime to client */
while (1) {
- timeval = time(NULL);
n = recvfrom(sock, buffer, MAXLINE, 0, (struct sockaddr *)&addr, &len);
if (n < 0) {
perror("recvfrom error");
printf("Request from host %s, port %d\n", buffer,
ntohs(addr.sin_port));
}
+ timeval = time(NULL);
snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&timeval));
n = sendto(sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&addr, sizeof(addr));
a questa problematica.
-
\subsection{Un server UDP elementare}
\label{sec:UDP_daytime_server}
macchina che ha inviato il pacchetto con un messaggio ICMP di tipo
\textit{port unreachable}.
+Una volta completata la fase di inizializzazione inizia il corpo principale
+(\texttt{\small 24--44}) del server, mantenuto all'interno di un ciclo
+infinito in cui si trattano le richieste. Il ciclo inizia (\texttt{\small 26})
+con una chiamata a \func{recvfrom}, che si bloccherà in attesa di pacchetti
+inviati dai client. Lo scopo della funzione è quello di ritornare tutte le
+volte che un pacchetto viene inviato al server, in modo da poter ricavare da
+esso l'indirizzo del client a cui inviare la risposta in \var{addr}. Per
+questo motivo in questo caso (al contrario di quanto fatto in
+\figref{fig:UDP_daytime_client}) si è avuto cura di passare gli opportuni
+argomenti alla funzione. Dopo aver controllato (\texttt{\small 27--30}) la
+presenza di eventuali errori (uscendo con un messaggio di errore qualora ve ne
+siano) si verifica (\texttt{\small 31}) se è stata attivata l'opzione
+\texttt{-v} (che imposta la variabile \var{verbose}) stampando nel caso
+(\texttt{\small 32--35}) l'indirizzo da cui si è appena ricevuto una richiesta
+(questa sezione è identica a quella del server TCP illustrato in
+\figref{fig:TCP_daytime_cunc_server_code}).
+
+Una volta ricevuta la richiesta resta solo da ottenere il tempo corrente
+(\texttt{\small 36}) e costruire (\texttt{\small 37}) la stringa di risposta,
+che poi verrà inviata (\texttt{\small 38}) al client usando \func{sendto},
+avendo al solito cura di controllare (\texttt{\small 40--42}) lo stato di
+uscita della funzione e trattando opportunamente la condizione di errore.
+
+Si noti come per le peculiarità del protocollo si sia utilizzato un server
+iterativo, che processa le richieste una alla volta via via che gli arrivano.
+Questa è una caratteristica comune dei server UDP, conseguenza diretta del
+fatto che non esiste il concetto di connessione, per cui non c'è la necessità
+di trattare separatamente le singole connessioni. Questo significa anche che è
+il kernel a gestire la possibilità di richieste multiple in contemporanea;
+quello che succede è semplicemente che il kernel accumula in un buffer in
+ingresso i pacchetti che arrivano e li restituisce al processo uno alla volta
+per ciascuna chiamata di \func{recvfrom}; è poi compito del server distribuire
+le risposte sulla base dell'indirizzo da cui provengono le richieste.
+
\section{I socket \textit{Unix domain}}
\label{sec:unix_socket}
-Benché i socket Unix domain non siano strattamente attinenti alla rete, in
+Benché i socket Unix domain non siano strettamente attinenti alla rete, in
quanto definiscono una interfaccia di comunicazione locale alla singola
macchina, li tratteremo comunque in questa sezione in quanto la loro
interfaccia è comunque basata sulla più generale interfaccia dei socket.
*
* Usage: daytimed -h give all info
*
- * $Id: UDP_daytimed.c,v 1.1 2004/03/21 18:30:35 piccardi Exp $
+ * $Id: UDP_daytimed.c,v 1.2 2004/03/21 23:01:01 piccardi Exp $
*
****************************************************************/
/*
}
/* write daytime to client */
while (1) {
- timeval = time(NULL);
n = recvfrom(sock, buffer, MAXLINE, 0, (struct sockaddr *)&addr, &len);
if (n < 0) {
perror("recvfrom error");
printf("Request from host %s, port %d\n", buffer,
ntohs(addr.sin_port));
}
+ timeval = time(NULL);
snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&timeval));
n = sendto(sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&addr, sizeof(addr));