X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=elemtcp.tex;h=ba1760aea3ca9009c2ed08ff282d43f5c7cee225;hp=f59308a68ad1ca52eef5b765c9086c420621e5df;hb=877a1d6577ab41ce13b0a2794b73885d98e0d7cc;hpb=ff2d0141751ed62ef56e5bfd226c589311b8b669 diff --git a/elemtcp.tex b/elemtcp.tex index f59308a..ba1760a 100644 --- a/elemtcp.tex +++ b/elemtcp.tex @@ -12,26 +12,27 @@ \label{cha:elem_TCP_sock} In questo capitolo iniziamo ad approfondire 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. +tratteremo qui dunque le varie funzioni che si sono usate nei due esempi +elementari forniti nel capitolo precedente (vedi \secref{sec:net_cli_sample} e +\secref{sec:net_serv_sample}), previa una descrizione delle principali +caratteristiche del funzionamento di una connessione TCP. \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 -per capire il modello di programmazione ed il funzionamento delle API. - -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\index{socket} attivo con l'uso del programma \cmd{netstat}. +utilizzano i socket TCP, è fondamentale spiegare alcune delle basi del +funzionamento del protocollo poiché questa conoscenza è essenziale per +comprendere il comportamento di dette funzioni per questi socket, ed il +relativo modello di programmazione. + +Il protocollo TCP serve a creare degli \textit{stream socket}, cioè un canale +di comunicazione che stabilisce una connessione fra due stazioni, in modo che +queste possano scambiarsi i dati. In questo capitolo ci concentreremo sulle +modalità con le quali il protocollo dà inizio e conclude una connessione e +faremo inoltre un breve accenno al significato di alcuni dei vari stati che +questa viene ad assumere durante la sua vita. \subsection{La creazione della connessione: il \textit{three way handshake}} \label{sec:TCPel_conn_cre} @@ -55,7 +56,7 @@ creazione di una connessione \textsl{apertura attiva}, dall'inglese \textit{active open}. La chiamata di \func{connect} blocca il processo e causa l'invio da parte del client di un segmento SYN,\footnote{Si ricordi che il segmento è l'unità elementare di - dati trasmessa dal protocollo TCP al livello superiore; tutti i segmenti + dati trasmessa dal protocollo TCP al livello successivo; tutti i segmenti hanno un header che contiene le informazioni che servono allo \textit{stack TCP} (così viene di solito chiamata la parte del kernel che implementa il protocollo) per realizzare la comunicazione, fra questi dati @@ -141,7 +142,7 @@ regolare la connessione. Normalmente vengono usate le seguenti opzioni: indicare un massimo di 65535 byte (anche se Linux usa come massimo 32767 per evitare problemi con alcuni stack bacati che usano l'aritmetica con segno per implementare lo stack TCP); ma alcuni tipi di connessione come quelle ad - alta velocità (sopra i 45Mbits/sec) e quelle che hanno grandi ritardi nel + alta velocità (sopra i 45Mbit/sec) e quelle che hanno grandi ritardi nel cammino dei pacchetti (come i satelliti) richiedono una finestra più grande per poter ottenere il massimo dalla trasmissione, per questo esiste questa opzione che indica un fattore di scala da applicare al valore della finestra @@ -150,7 +151,7 @@ regolare la connessione. Normalmente vengono usate le seguenti opzioni: attiva prevede come negoziazione che l'altro capo della connessione riconosca esplicitamente l'opzione inserendola anche lui nel suo SYN di risposta dell'apertura della connessione.} per la connessione corrente - (espresso come numero di bit cui shiftare a sinistra il valore della + (espresso come numero di bit cui spostare a sinistra il valore della finestra annunciata inserito nel pacchetto). \item \textit{timestamp option}, è anche questa una nuova opzione necessaria @@ -324,10 +325,9 @@ dati rispondono meglio alle esigenze che devono essere affrontate. Come riportato da Stevens in \cite{UNP1} lo stato \texttt{TIME\_WAIT} è probabilmente uno degli aspetti meno compresi del protocollo TCP, è infatti -comune trovare nei newsgroup domande su come sia possibile evitare che -un'applicazione resti in questo stato lasciando attiva una connessione ormai -conclusa; la risposta è che non deve essere fatto, ed il motivo cercheremo di -spiegarlo adesso. +comune trovare domande su come sia possibile evitare che un'applicazione resti +in questo stato lasciando attiva una connessione ormai conclusa; la risposta è +che non deve essere fatto, ed il motivo cercheremo di spiegarlo adesso. Come si è visto nell'esempio precedente (vedi \figref{fig:TPCel_conn_example}) \texttt{TIME\_WAIT} è lo stato finale in cui il capo di una connessione che @@ -339,12 +339,12 @@ La MSL sulla rete; questo tempo è limitato perché ogni pacchetto IP può essere ritrasmesso dai router un numero massimo di volte (detto \textit{hop limit}). Il numero di ritrasmissioni consentito è indicato dal campo TTL dell'header di -IP (per maggiori dettagli vedi \secref{sec:IP_xxx}), e viene decrementato -ad ogni passaggio da un router; quando si annulla il pacchetto viene scartato. -Siccome il numero è ad 8 bit il numero massimo di ``salti'' è di 255, pertanto -anche se il TTL (da \textit{time to live}) non è propriamente un limite sul -tempo di vita, si stima che un pacchetto IP non possa restare nella rete per -più di MSL secondi. +IP (per maggiori dettagli vedi \secref{sec:IP_xxx}), e viene decrementato ad +ogni passaggio da un router; quando si annulla il pacchetto viene scartato. +Siccome il numero è ad 8 bit il numero massimo di ``\textsl{salti}'' è di 255, +pertanto anche se il TTL (da \textit{time to live}) non è propriamente un +limite sul tempo di vita, si stima che un pacchetto IP non possa restare nella +rete per più di MSL secondi. Ogni implementazione del TCP deve scegliere un valore per la MSL (l'RFC~1122 raccomanda 2 minuti, Linux usa 30 secondi), questo comporta una durata dello @@ -701,10 +701,7 @@ Per specificare un indirizzo generico con IPv4 si usa il valore \const{INADDR\_ANY}, il cui valore, come visto anche negli esempi precedenti è pari a zero, nell'esempio \figref{fig:net_serv_code} si è usata un'assegnazione immediata del tipo: - -\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} -serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ -\end{lstlisting} +\includecodesnip{listati/serv_addr_sin_addr.c} Si noti che si è usato \func{htonl} per assegnare il valore \const{INADDR\_ANY}, benché essendo questo pari a zero il riordinamento sia @@ -742,10 +739,11 @@ Per questo motivo nell'header \file{netinet/in.h} \const{in6addr\_any} (dichiarata come \direct{extern}, ed inizializzata dal sistema al valore \const{IN6ADRR\_ANY\_INIT}) che permette di effettuare una assegnazione del tipo: +\includecodesnip{listati/serv_addr_sin6_addr.c} +in maniera analoga si può utilizzare la variabile \const{in6addr\_loopback} +per indicare l'indirizzo di \textit{loopback}, che a sua volta viene +inizializzata staticamente a \const{IN6ADRR\_LOOPBACK\_INIT}. -\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} -serv_add.sin6_addr = in6addr_any; /* connect from anywhere */ -\end{lstlisting} \subsection{La funzione \func{connect}} @@ -1042,7 +1040,7 @@ prima connessione completa (estratta dalla relativa coda, vedi socket \param{sockfd}. Quest'ultimo (detto \textit{listening socket}) è quello creato all'inizio e messo in ascolto con \func{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 imopstato il socket +mette in attesa il processo\footnote{a meno che non si sia impostato il socket per essere non bloccante (vedi \secref{sec:file_noblocking}), nel qual caso ritorna con l'errore \errcode{EAGAIN}. Torneremo su questa modalità di operazione in \secref{sec:xxx_sock_noblock}.} fintanto che non ne arriva @@ -1119,61 +1117,11 @@ rispetto al precedente esempio. Al solito il sorgente completo del server \file{ElemDaytimeTCPCuncServ.c} è allegato nella directory dei sorgenti. \begin{figure}[!htb] - \footnotesize - \begin{lstlisting}{} -#include /* predefined types */ -#include /* include unix standard library */ -#include /* IP addresses conversion utiliites */ -#include /* socket library */ -#include /* include standard I/O library */ -#include - -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} + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/ElemDaytimeTCPCuncServ.c} + \end{minipage} + \normalsize \caption{Esempio di codice di un server concorrente elementare per il servizio daytime.} \label{fig:TCPel_serv_code} @@ -1222,7 +1170,7 @@ chiusa. \subsection{Le funzioni \func{getsockname} e \func{getpeername}} \label{sec:TCPel_get_names} -Queste due funzioni vengono usate per ottenere i dati realtivi alla socket +Queste due funzioni vengono usate per ottenere i dati relativi alla socket pair associata ad un certo socket; la prima è \funcd{getsockname} e restituisce l'indirizzo locale; il suo prototipo è: \begin{prototype}{sys/socket.h}