X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=tcpsock.tex;h=613aea4de6e9afa31dfdbee8925dc179d4b01bc8;hp=8118b1e49db1067d5ae69627623a2daac271e736;hb=6c2be511ebf59148d64ae0da7f44e21b2bd92e73;hpb=beece18eba2dcc2a9b915dab61277df8685a3da6 diff --git a/tcpsock.tex b/tcpsock.tex index 8118b1e..613aea4 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -1,6 +1,6 @@ %% tcpsock.tex %% -%% Copyright (C) 2000-2014 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2015 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free %% Documentation License, Version 1.1 or any later version published by the %% Free Software Foundation; with the Invariant Sections being "Un preambolo", @@ -144,29 +144,28 @@ connessione. Normalmente vengono usate le seguenti opzioni: sez.~\ref{sec:sock_tcp_udp_options}). \item \textit{window scale option}, il protocollo TCP implementa il controllo - di flusso attraverso una \itindex{advertised~window} \textit{advertised - window} (la ``\textsl{finestra 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 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 - \itindex{advertised~window} 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 (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} \itindex{TCP~window~scaling} \texttt{tcp\_window\_scaling} - (vedi sez.~\ref{sec:sock_ipv4_sysctl}).\footnote{per poter usare questa + di flusso attraverso una \textit{advertised window} (la ``\textsl{finestra + 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 + 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 + (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} \itindex{TCP~window~scaling} + \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}) @@ -1299,7 +1298,7 @@ Quando ci si trova ad affrontare questo comportamento tutto quello che si deve fare è semplicemente ripetere la lettura (o la scrittura) per la quantità di byte restanti, tenendo conto che le funzioni si possono bloccare se i dati non sono disponibili: è lo stesso comportamento che si può avere scrivendo più di -\const{PIPE\_BUF} byte in una pipe (si riveda quanto detto in +\const{PIPE\_BUF} byte in una \textit{pipe} (si riveda quanto detto in sez.~\ref{sec:ipc_pipes}). Per questo motivo, seguendo l'esempio di R. W. Stevens in \cite{UNP1}, si sono @@ -2400,13 +2399,13 @@ si aveva il SYN flag attivo. Si noti come a partire dal secondo pacchetto sia sempre attivo il campo \texttt{ack}, seguito dal numero di sequenza per il quale si da il ricevuto; quest'ultimo, a partire dal terzo pacchetto, viene espresso in forma relativa per maggiore compattezza. Il campo \texttt{win} in -ogni riga indica la \itindex{advertised~window} \textit{advertised window} di -cui parlavamo in sez.~\ref{sec:TCP_TCP_opt}. Allora si può verificare -dall'output del comando come venga appunto realizzata la sequenza di pacchetti -descritta in sez.~\ref{sec:TCP_conn_cre}: prima viene inviato dal client un -primo pacchetto con il SYN che inizia la connessione, a cui il server risponde -dando il ricevuto con un secondo pacchetto, che a sua volta porta un SYN, cui -il client risponde con un il terzo pacchetto di ricevuto. +ogni riga indica la \textit{advertised window} di cui parlavamo in +sez.~\ref{sec:TCP_TCP_opt}. Allora si può verificare dall'output del comando +come venga appunto realizzata la sequenza di pacchetti descritta in +sez.~\ref{sec:TCP_conn_cre}: prima viene inviato dal client un primo pacchetto +con il SYN che inizia la connessione, a cui il server risponde dando il +ricevuto con un secondo pacchetto, che a sua volta porta un SYN, cui il client +risponde con un il terzo pacchetto di ricevuto. Ritorniamo allora alla nostra sessione con il servizio echo: dopo le tre righe del \itindex{three~way~handshake} \textit{three way handshake} non avremo @@ -2492,12 +2491,12 @@ Per capire come questa avvenga comunque, non avendo inserito nel codice nessun controllo di errore, occorre ricordare che, a parte la bidirezionalità del flusso dei dati, dal punto di vista del funzionamento nei confronti delle funzioni di lettura e scrittura, i socket sono del tutto analoghi a delle -pipe. Allora, da quanto illustrato in sez.~\ref{sec:ipc_pipes}, sappiamo che -tutte le volte che si cerca di scrivere su una pipe il cui altro capo non è -aperto il lettura il processo riceve un segnale di \signal{SIGPIPE}, e questo è -esattamente quello che avviene in questo caso, e siccome non abbiamo un -gestore per questo segnale, viene eseguita l'azione preimpostata, che è quella -di terminare il processo. +\textit{pipe}. Allora, da quanto illustrato in sez.~\ref{sec:ipc_pipes}, +sappiamo che tutte le volte che si cerca di scrivere su una \textit{pipe} il +cui altro capo non è aperto il lettura il processo riceve un segnale di +\signal{SIGPIPE}, e questo è esattamente quello che avviene in questo caso, e +siccome non abbiamo un gestore per questo segnale, viene eseguita l'azione +preimpostata, che è quella di terminare il processo. Per gestire in maniera più corretta questo tipo di evento dovremo allora modificare il nostro client perché sia in grado di trattare le varie tipologie @@ -2773,13 +2772,14 @@ sappiamo che la funzione ritorna quando uno o più dei file descriptor messi sotto controllo è pronto per la relativa operazione. In quell'occasione non abbiamo però definito cosa si intende per pronto, -infatti per dei normali file, o anche per delle pipe, la condizione di essere -pronti per la lettura o la scrittura è ovvia; invece lo è molto meno nel caso -dei socket, visto che possono intervenire tutte una serie di possibili -condizioni di errore dovute alla rete. Occorre allora specificare chiaramente -quali sono le condizioni per cui un socket risulta essere ``\textsl{pronto}'' -quando viene passato come membro di uno dei tre \itindex{file~descriptor~set} -\textit{file descriptor set} usati da \func{select}. +infatti per dei normali file, o anche per delle \textit{pipe}, la condizione +di essere pronti per la lettura o la scrittura è ovvia; invece lo è molto meno +nel caso dei socket, visto che possono intervenire tutte una serie di +possibili condizioni di errore dovute alla rete. Occorre allora specificare +chiaramente quali sono le condizioni per cui un socket risulta essere +``\textsl{pronto}'' quando viene passato come membro di uno dei tre +\itindex{file~descriptor~set} \textit{file descriptor set} usati da +\func{select}. Le condizioni che fanno si che la funzione \func{select} ritorni segnalando che un socket (che sarà riportato nel primo insieme di file descriptor) è