Riscritta la parte di accept. Inserite le parti relative al comportamento
authorSimone Piccardi <piccardi@gnulinux.it>
Thu, 17 May 2001 22:56:40 +0000 (22:56 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Thu, 17 May 2001 22:56:40 +0000 (22:56 +0000)
specifico su linux prese dalle manpages

elemtcp.tex

index 9eab58a2adf71cb073b6562dd5c17e3740f31069..fcb3b32ec8c98f279bb6acf51b05cb0974e90931 100644 (file)
@@ -1,27 +1,28 @@
 \chapter{Socket TCP elementari}
 \label{cha:elem_TCP_sock}
 
-In questo capitolo inizieremo ad approndire la conoscenza dei socket TCP,
+In questo capitolo iniziamo ad approndire la conoscenza dei socket TCP,
 tratteremo qui dunque il funzionamento delle varie funzioni che si sono usate
 nei due esempi elementari forniti in precedenza (vedi
 \secref{sec:net_cli_sample} e \secref{sec:net_serv_sample}), previa una
 descrizione delle principali caratteristiche del funzionamento di una
 connessione TCP.
 
-La seconda parte del capitolo sarà poi dedicata alla scrittura di una prima
-semplice applicazione client/server completa, che implementi il servizio
-standard \texttt{echo} su TCP.
+Infine riscriveremo il precedente esempio elementare di server
+\texttt{daytime} in una forma appena più evoluta (come server concorrente) e
+con alcune caratteristiche aggiuntive che mettano in luce quanto andremo ad
+illustrare.
 
 \section{Il funzionamento di una connessione TCP}
 \label{sec:TCPel_connession}
 
 Prima di entrare nei dettagli delle funzioni usate nelle applicazioni che
 utilizzano i socket TCP, è fondamentale spiegare alcune basi del funzionamento
-del TCP, la conoscenza del funzionamento del protocollo è infatti essenziale
+del TCP; la conoscenza del funzionamento del protocollo è infatti essenziale
 per capire il modello di programmazione ed il funzionamento delle API.
 
-In particolare ci concentreremo sulle modalità con le quali il protocollo da
-inizio e conclude una connessione; faremo anche un breve accenno al
+In particolare ci concentreremo sulle modalità con le quali il protocollo dà
+inizio e conclude una connessione; faremo inoltre anche un breve accenno al
 significato di alcuni dei vari stati che il protocollo assume durante la vita
 di una connessione, che possono essere osservati per ciascun socket attivo con
 l'uso del programma \texttt{netstat}.
@@ -716,7 +717,7 @@ La funzione \texttt{connect} 
 connessione con un server TCP, il prototipo della funzione è il seguente:
 
 \begin{prototype}{sys/socket.h}
-{int connect(int sockfd, const struct sockaddr *serv\_addr, socklen\_t addrlen)}
+{int connect(int sockfd, const struct sockaddr *servaddr, socklen\_t addrlen)}
   
   Il primo argomento è un file descriptor ottenuto da una precedente chiamata
   a \texttt{socket}, mentre il secondo e terzo argomento sono rispettivamente
@@ -919,7 +920,6 @@ lasciare la gestione della connessione alla ritrasmissione prevista dal
 protocollo TCP.
 
 
-
 \subsection{La funzione \texttt{accept}}
 \label{sec:TCPel_func_accept}
 
@@ -929,15 +929,14 @@ funzione restituisce un nuovo socket descriptor su cui si potr
 effettuare la comunicazione. Se non ci sono connessioni completate il processo
 viene messo in attesa. Il prototipo della funzione è il seguente:
 
-
 \begin{prototype}{sys/socket.h}
-{int listen(int sockfd, struct sockaddr *addr, socklen\_t *addrlen)}  
-  La funzione estrae la prima connessione completa relativa al socket
-  \texttt{sockfd} in attesa sulla coda delle connessioni complete che associa
-  nuovo socket con le stesse caratteristiche di \texttt{sockfd} (restituito
-  dalla funzione stessa). Il socket originale non viene toccato. Nella
-  struttura \texttt{addr} e nella variabile \texttt{addrlen} vengono
-  restituiti indirizzo e relativa lunghezza del client che si è connesso.
+{int listen(int sockfd, struct sockaddr *addr, socklen\_t *addrlen)} 
+  La funzione estrae la prima connessione relativa al socket \texttt{sockfd}
+  in attesa sulla coda delle connessioni complete, che associa ad nuovo socket
+  con le stesse caratteristiche di \texttt{sockfd} (restituito dalla funzione
+  stessa).  Il socket originale non viene toccato. Nella struttura
+  \texttt{addr} e nella variabile \texttt{addrlen} vengono restituiti
+  indirizzo e relativa lunghezza del client che si è connesso.
  
   La funzione restituisce un numero di socket descriptor positivo in caso di
   successo e -1 in caso di errore, nel qual caso la variabile \texttt{errno}
@@ -959,6 +958,13 @@ viene messo in attesa. Il prototipo della funzione 
   \item \texttt{ENOBUFS, ENOMEM} Not enough free memory.  This often means
     that the memory allocation is limited by the socket buffer limits, not by
     the system memory.
+    Inoltre possono essere restituiti gli errori di rete relativi al nuovo
+    socket come: \texttt{EMFILE}, \texttt{EINVAL}, \texttt{ENOSR},
+    \texttt{ENOBUFS}, \texttt{EPERM}, \texttt{ECONNABORTED},
+    \texttt{ESOCKTNOSUPPORT}, \texttt{EPROTONOSUPPORT}, \texttt{ETIMEDOUT},
+    \texttt{ERESTARTSYS}.
+
   \end{errlist}
 \end{prototype}
 
@@ -971,26 +977,48 @@ connessioni, la conferma della connessione viene fatta implicitamente dalla
 prima chiamata ad una \texttt{read} o una \texttt{write} mentre il rifiuto
 della connessione viene fatta con la funzione \texttt{close}.
 
+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
+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.
+
 I due parametri \texttt{cliaddr} e \texttt{addrlen} (si noti che quest'ultimo
 è passato per indirizzo per avere indietro il valore) sono usati per ottenere
 l'indirizzo del client da cui proviene la connessione. Prima della chiamata
 \texttt{addrlen} deve essere inizializzato alle dimensioni della struttura il
-cui indirizzo è passato come parametro in \texttt{cliaddr}, al rientro della
+cui indirizzo è passato come parametro in \texttt{cliaddr}, al ritorno della
 funzione \texttt{addrlen} conterrà il numero di bytes scritti dentro
-\texttt{cliaddr}.
-
-Se la funzione ha successo restituisce un nuovo socket descriptor, detto
-\textit{connected socket}, su cui è agganciata la connessione che il client
-TCP ha effettuato verso il socket \texttt{sockfd}. Quest'ultimo, che viene
-chiamato invece \textit{listening socket}, deve essere stato creato in
-precedenza e messo in ascolto con \texttt{listen}, e non viene toccato dalla
-funzione. 
-
-Questa distinzione è essenziale per capire 
+\texttt{cliaddr}. Se questa informazione non interessa basterà inizializzare a
+\texttt{NULL} detti puntatori.
+
+Se la funzione ha successo restituisce il descrittore di un nuovo socket
+creato dal kernel (detto \textit{connected socket}) a cui viene associata la
+prima connessione completa (estratta dalla relativa coda, vedi
+\secref{sec:TCPel_func_listen}) che il client TCP ha effettuato verso il
+socket \texttt{sockfd}. Quest'ultimo (detto \textit{listening socket}) è
+quello creato all'inizio e messo in ascolto con \texttt{listen}, e non viene
+toccato dalla funzione.  
+
+Se non ci sono connessioni pendenti da accettare la funzione mette in attesa
+il processo\footnote{a meno che non si sia settato il socket per essere
+  non-bloccante, nel qual caso ritorna con l'errore \texttt{EAGAIN},
+  torneremo su questa modalità di operazione in \secref{sec:xxx_sock_noblock}}
+fintanto che non ne arriva una.
+Questo meccanismo è essenziale per capire il funzionamento di un server, in
+generale infatti c'è sempre un solo socket in ascolto, che resta per tutto il
+tempo nello stato \texttt{LISTEN}, mentre le connessioni vengono gestite dai
+nuovi socket ritornati da \texttt{accept} che sono posti automaticamente nello
+stato \texttt{ESTABLISHED} e utilizzati fino alla chiusura della connessione
+che avviene su di essi.  Si può riconoscere questo schema anche nell'esempio
+elementare in \figref{fig:net_serv_code} dove per ogni connessione il socket
+creato da \texttt{accept} viene chiuso dopo l'invio dei dati.
 
 
+\section{Un server concorrente su TCP}
+\label{sec:TCPel_cunc_serv}
 
-\section{Una semplice implementazione del servizio \texttt{echo} su TCP}
-\label{sec:TCPel_echo_example}
 
-Veniamo ora ad una applicazione