From: Simone Piccardi Date: Wed, 13 Apr 2016 08:25:28 +0000 (+0000) Subject: Correzioni fatte in coda dal dottore. X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=018e390e5d015496ccd871868651e69ebab49cec;p=gapil.git Correzioni fatte in coda dal dottore. --- diff --git a/tcpsock.tex b/tcpsock.tex index b408819..d11e6a5 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -30,10 +30,10 @@ il relativo modello di programmazione. Si ricordi che il protocollo TCP serve a creare degli \textit{stream socket}, cioè una forma di canale di comunicazione che stabilisce una connessione -stabile fra due stazioni, in modo che queste possano scambiarsi dei dati. In -questa sezione 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 \textsl{stati} ad essa associati. +stabile fra due macchine in rete, in modo che queste possano scambiarsi dei +dati. In questa sezione 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 \textsl{stati} ad essa associati. \subsection{La creazione della connessione: il \textit{three way handshake}} @@ -43,16 +43,17 @@ significato di alcuni dei vari \textsl{stati} ad essa associati. Il processo che porta a creare una connessione TCP viene chiamato \textit{three way handshake}; la successione tipica degli eventi (e dei -\textsl{segmenti}\footnote{si ricordi che il segmento è l'unità elementare di - 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 ci sono una - serie di flag usati per gestire la connessione, come SYN, ACK, URG, FIN, - alcuni di essi, come SYN (che sta per \textit{syncronize}) corrispondono a - funzioni particolari del protocollo e danno il nome al segmento, (per - maggiori dettagli vedere sez.~\ref{sec:tcp_protocol}).} di dati che vengono -scambiati) che porta alla creazione di una connessione è la seguente: +\textsl{segmenti}\footnote{si ricordi che il \textsl{segmento} è l'unità + elementare di dati trasmessa dal protocollo TCP al livello successivo; tutti + i segmenti hanno una intestazione 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 ci sono una serie di flag usati per gestire la connessione, come SYN, + ACK, URG, FIN, alcuni di essi, come SYN (che sta per \textit{syncronize}) + corrispondono a funzioni particolari del protocollo e danno il nome al + segmento, (per maggiori dettagli vedere sez.~\ref{sec:tcp_protocol}).} di +dati che vengono scambiati) che porta alla creazione di una connessione è la +seguente: \begin{enumerate} \item Il server deve essere preparato per accettare le connessioni in arrivo; @@ -70,20 +71,20 @@ scambiati) che porta alla creazione di una connessione è la seguente: contiene solo gli header IP e TCP (con il numero di sequenza iniziale e il flag SYN) e le opzioni di TCP. -\item il server deve dare ricevuto (l'\textit{acknowledge}) del SYN del +\item Il server deve dare ricevuto (l'\textit{acknowledge}) del SYN del client, inoltre anche il server deve inviare il suo SYN al client (e trasmettere il suo numero di sequenza iniziale) questo viene fatto ritrasmettendo un singolo segmento in cui sono impostati entrambi i flag SYN e ACK. -\item una volta che il client ha ricevuto l'acknowledge dal server la funzione - \func{connect} ritorna, l'ultimo passo è dare il ricevuto del SYN del - server inviando un ACK. Alla ricezione di quest'ultimo la funzione +\item Una volta che il client ha ricevuto l'\textit{acknowledge} dal server la + funzione \func{connect} ritorna, l'ultimo passo è dare il ricevuto del SYN + del server inviando un ACK. Alla ricezione di quest'ultimo la funzione \func{accept} del server ritorna e la connessione è stabilita. \end{enumerate} Il procedimento viene chiamato \textit{three way handshake} dato che per -realizzarlo devono essere scambiati tre segmenti. In fig.~\ref{fig:TCP_TWH} +realizzarlo devono essere scambiati tre segmenti. In fig.~\ref{fig:TCP_TWH} si è rappresentata graficamente la sequenza di scambio dei segmenti che stabilisce la connessione. @@ -102,6 +103,8 @@ stabilisce la connessione. \label{fig:TCP_TWH} \end{figure} +\index{numeri~di~sequenza|(} + Si è accennato in precedenza ai \textsl{numeri di sequenza} (che sono anche riportati in fig.~\ref{fig:TCP_TWH}): per gestire una connessione affidabile infatti il protocollo TCP prevede nell'header la presenza di un numero a 32 @@ -111,15 +114,17 @@ contenuta nel segmento. Il numero di sequenza di ciascun segmento viene calcolato a partire da un \textsl{numero di sequenza iniziale} generato in maniera casuale del kernel -all'inizio della connessione e trasmesso con il SYN; l'acknowledgement di -ciascun segmento viene effettuato dall'altro capo della connessione impostando -il flag ACK e restituendo nell'apposito campo dell'header un -\textit{acknowledge number}) pari al numero di sequenza che il ricevente si -aspetta di ricevere con il pacchetto successivo; dato che il primo pacchetto -SYN consuma un byte, nel \textit{three way handshake} il numero di acknowledge -è sempre pari al numero di sequenza iniziale incrementato di uno; lo stesso -varrà anche (vedi fig.~\ref{fig:TCP_close}) per l'acknowledgement di un FIN. - +all'inizio della connessione e trasmesso con il SYN; +l'\textit{acknowledgement} di ciascun segmento viene effettuato dall'altro +capo della connessione impostando il flag ACK e restituendo nell'apposito +campo dell'header un \textit{acknowledge number}) pari al numero di sequenza +che il ricevente si aspetta di ricevere con il pacchetto successivo; dato che +il primo pacchetto SYN consuma un byte, nel \textit{three way handshake} il +numero di \textit{acknowledge} è sempre pari al numero di sequenza iniziale +incrementato di uno; lo stesso varrà anche (vedi fig.~\ref{fig:TCP_close}) per +l'\textit{acknowledgement} di un FIN. + +\index{numeri~di~sequenza|)} \itindend{three~way~handshake} @@ -127,12 +132,12 @@ varrà anche (vedi fig.~\ref{fig:TCP_close}) per l'acknowledgement di un FIN. \label{sec:TCP_TCP_opt} Ciascun segmento SYN contiene in genere delle opzioni per il protocollo TCP, -le cosiddette \textit{TCP options},\footnote{da non confondere con le opzioni - dei socket TCP che tratteremo in sez.~\ref{sec:sock_tcp_udp_options}, in - questo caso si tratta delle opzioni che vengono trasmesse come parte di un - pacchetto TCP, non delle funzioni che consentono di impostare i relativi - valori.} che vengono inserite fra l'header e i dati, e che servono a -comunicare all'altro capo una serie di parametri utili a regolare la +le cosiddette \textit{TCP options}, da non confondere con le opzioni dei +socket TCP che tratteremo in sez.~\ref{sec:sock_tcp_udp_options}; in questo +caso infatti si tratta delle opzioni che vengono trasmesse come parte di un +pacchetto TCP, e non delle funzioni che consentono di impostare i relativi +valori. Queste opzioni vengono inserite fra l'intestazione ed i dati, e +servono a comunicare all'altro capo una serie di parametri utili a regolare la connessione. Normalmente vengono usate le seguenti opzioni: \begin{itemize} @@ -148,42 +153,45 @@ connessione. Normalmente vengono usate le seguenti opzioni: annunciata}'', vedi sez.~\ref{sec:tcp_protocol_xxx}) con la quale ciascun capo della comunicazione dichiara quanto spazio disponibile ha in memoria per i dati. Questo è un numero a 16 bit dell'header, che così può indicare - un massimo di 65535 byte;\footnote{in Linux il massimo è 32767 per evitare + un massimo di 65535 byte\footnote{in Linux il massimo è 32767 per evitare problemi con alcune implementazioni che usano l'aritmetica con segno per implementare lo stack TCP.} ma alcuni tipi di connessione come quelle ad 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 - annunciata\footnote{essendo una nuova opzione per garantire la compatibilità - con delle vecchie implementazioni del protocollo la procedura che la - 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 + per poter ottenere il massimo dalla trasmissione. + + Per questo esiste un'altra opzione che indica un fattore di scala da + applicare al valore della finestra annunciata per la connessione corrente (espresso come numero di bit cui spostare a sinistra il valore della - finestra annunciata inserito nel pacchetto). Con Linux è possibile indicare - al kernel di far negoziare il fattore di scala in fase di creazione di una - connessione tramite la \textit{sysctl} \texttt{tcp\_window\_scaling} (vedi - sez.~\ref{sec:sock_ipv4_sysctl}).\footnote{per poter usare questa - funzionalità è comunque necessario ampliare le dimensioni dei buffer di - ricezione e spedizione, cosa che può essere fatta sia a livello di sistema - con le opportune \textit{sysctl} (vedi sez.~\ref{sec:sock_ipv4_sysctl}) - che a livello di singoli socket con le relative opzioni (vedi - sez.~\ref{sec:sock_tcp_udp_options}).} + finestra annunciata inserito nel pacchetto). Essendo una nuova opzione per + garantire la compatibilità con delle vecchie implementazioni del protocollo + la procedura che la 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. + + Con Linux è possibile indicare al kernel di far negoziare il fattore di + scala in fase di creazione di una connessione tramite la \textit{sysctl} + \texttt{tcp\_window\_scaling} (vedi sez.~\ref{sec:sock_ipv4_sysctl}). Per + poter usare questa funzionalità è comunque necessario ampliare le dimensioni + dei buffer di ricezione e spedizione, cosa che può essere fatta sia a + livello di sistema con le opportune \textit{sysctl} (vedi + sez.~\ref{sec:sock_ipv4_sysctl}) che a livello di singoli socket con le + relative opzioni (vedi sez.~\ref{sec:sock_tcp_udp_options}). \item \textit{timestamp option}, è anche questa una nuova opzione necessaria per le connessioni ad alta velocità per evitare possibili corruzioni di dati - dovute a pacchetti perduti che riappaiono; anche questa viene negoziata come - la precedente. + dovute a pacchetti perduti che riappaiono; anche questa viene negoziata + all'inizio della connessione come la precedente. \end{itemize} -La MSS è generalmente supportata da quasi tutte le implementazioni del -protocollo, le ultime due opzioni (trattate +La \textit{MSS option} è generalmente supportata da quasi tutte le +implementazioni del protocollo, le ultime due opzioni (trattate nell'\href{http://www.ietf.org/rfc/rfc1323.txt}{RFC~1323}) sono meno comuni; vengono anche dette \textit{long fat pipe options} dato che questo è il nome che viene dato alle connessioni caratterizzate da alta velocità o da ritardi -elevati. In ogni caso Linux supporta pienamente entrambe le opzioni. +elevati. In ogni caso Linux supporta pienamente entrambe queste opzioni +aggiuntive. \subsection{La terminazione della connessione} @@ -203,13 +211,13 @@ caso la successione degli eventi è la seguente: \textsl{chiusura passiva} (o \textit{passive close}). Al FIN, come ad ogni altro pacchetto, viene risposto con un ACK, inoltre il ricevimento del FIN viene segnalato al processo che ha aperto il socket (dopo che ogni altro - eventuale dato rimasto in coda è stato ricevuto) come un end-of-file sulla - lettura: questo perché il ricevimento di un FIN significa che non si - riceveranno altri dati sulla connessione. + eventuale dato rimasto in coda è stato ricevuto) come un + \textit{end-of-file} sulla lettura: questo perché il ricevimento di un FIN + significa che non si riceveranno altri dati sulla connessione. -\item Una volta rilevata l'end-of-file anche il secondo processo chiamerà la - funzione \func{close} sul proprio socket, causando l'emissione di un altro - segmento FIN. +\item Una volta rilevata l'\textit{end-of-file} anche il secondo processo + chiamerà la funzione \func{close} sul proprio socket, causando l'emissione + di un altro segmento FIN. \item L'altro capo della connessione riceverà il FIN conclusivo e risponderà con un ACK. @@ -219,8 +227,10 @@ Dato che in questo caso sono richiesti un FIN ed un ACK per ciascuna direzione normalmente i segmenti scambiati sono quattro. Questo non è vero sempre giacché in alcune situazioni il FIN del passo 1) è inviato insieme a dei dati. Inoltre è possibile che i segmenti inviati nei passi 2 e 3 dal capo che -effettua la chiusura passiva, siano accorpati in un singolo segmento. In -fig.~\ref{fig:TCP_close} si è rappresentato graficamente lo sequenza di +effettua la chiusura passiva, siano accorpati in un singolo segmento. Come per +il SYN anche il FIN occupa un byte nel numero di sequenza, per cui l'ACK +riporterà un \textit{acknowledge number} incrementato di uno. In +fig.~\ref{fig:TCP_close} si è rappresentata graficamente la sequenza di scambio dei segmenti che conclude la connessione. \begin{figure}[!htb] @@ -229,8 +239,6 @@ scambio dei segmenti che conclude la connessione. \label{fig:TCP_close} \end{figure} -Come per il SYN anche il FIN occupa un byte nel numero di sequenza, per cui -l'ACK riporterà un \textit{acknowledge number} incrementato di uno. Si noti che, nella sequenza di chiusura, fra i passi 2 e 3, è in teoria possibile che si mantenga un flusso di dati dal capo della connessione che @@ -252,9 +260,11 @@ Infine occorre sottolineare che, benché nella figura (e nell'esempio che vedremo più avanti in sez.~\ref{sec:TCP_echo}) sia stato il client ad eseguire la chiusura attiva, nella realtà questa può essere eseguita da uno qualunque dei due capi della comunicazione (come nell'esempio di -fig.~\ref{fig:TCP_daytime_iter_server_code}), e anche se il caso più comune -resta quello del client, ci sono alcuni servizi, il principale dei quali è -l'HTTP, per i quali è il server ad effettuare la chiusura attiva. +fig.~\ref{fig:TCP_daytime_iter_server_code}), e che anche se il caso più +comune resta quello del client, ci sono alcuni servizi, il più noto dei quali +è l'HTTP,\footnote{la cosa si applica sempre per la versione 1.0, con le + versioni successive il default è cambiato.} per i quali è il server ad +effettuare la chiusura attiva. \subsection{Un esempio di connessione}