X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=tcpsock.tex;h=613aea4de6e9afa31dfdbee8925dc179d4b01bc8;hp=6b28862a93d1f5b307d622490535dd22a3a4b3cb;hb=6c2be511ebf59148d64ae0da7f44e21b2bd92e73;hpb=4aa6c51696d2b11c572eccd37238db1691785573 diff --git a/tcpsock.tex b/tcpsock.tex index 6b28862..613aea4 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -1,6 +1,6 @@ %% tcpsock.tex %% -%% Copyright (C) 2000-2012 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", @@ -135,37 +135,37 @@ comunicare all'altro capo una serie di parametri utili a regolare la connessione. Normalmente vengono usate le seguenti opzioni: \begin{itemize} -\item \textit{MSS option}, dove MMS sta per \itindex{Maximum~Segment~Size} - \textit{Maximum Segment Size}, con questa opzione ciascun capo della - connessione annuncia all'altro il massimo ammontare di dati che vorrebbe - accettare per ciascun segmento nella connessione corrente. È possibile - leggere e scrivere questo valore attraverso l'opzione del socket - \const{TCP\_MAXSEG} (vedi sez.~\ref{sec:sock_tcp_udp_options}). +\item \textit{MSS option}, dove MMS sta per + \itindex{Maximum~Segment~Size~(MSS)} \textit{Maximum Segment Size}, con + questa opzione ciascun capo della connessione annuncia all'altro il massimo + ammontare di dati che vorrebbe accettare per ciascun segmento nella + connessione corrente. È possibile leggere e scrivere questo valore + attraverso l'opzione del socket \const{TCP\_MAXSEG} (vedi + 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}) @@ -179,8 +179,8 @@ connessione. Normalmente vengono usate le seguenti opzioni: \end{itemize} -La MSS \itindex{Maximum~Segment~Size} è generalmente supportata da quasi tutte -le implementazioni del protocollo, le ultime due opzioni (trattate +La MSS \itindex{Maximum~Segment~Size~(MSS)} è 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 @@ -304,9 +304,9 @@ che il protocollo viene ad assumere per i due lati, server e client. \end{figure} La connessione viene iniziata dal client che annuncia una -\itindex{Maximum~Segment~Size} MSS di 1460, un valore tipico con Linux per -IPv4 su Ethernet, il server risponde con lo stesso valore (ma potrebbe essere -anche un valore diverso). +\itindex{Maximum~Segment~Size~(MSS)} MSS di 1460, un valore tipico con Linux +per IPv4 su Ethernet, il server risponde con lo stesso valore (ma potrebbe +essere anche un valore diverso). Una volta che la connessione è stabilita il client scrive al server una richiesta (che assumiamo stare in un singolo segmento, cioè essere minore dei @@ -518,7 +518,7 @@ un socket solo da un processo con i privilegi di amministratore, per far sì che solo l'amministratore possa allocare queste porte per far partire i relativi servizi. -Le \textsl{glibc} definiscono (in \texttt{netinet/in.h}) +Le \textsl{glibc} definiscono in \headfile{netinet/in.h} \const{IPPORT\_RESERVED} e \const{IPPORT\_USERRESERVED}, in cui la prima (che vale 1024) indica il limite superiore delle porte riservate, e la seconda (che vale 5000) il limite inferiore delle porte a disposizione degli utenti. La @@ -577,7 +577,7 @@ posto in ascolto per connessioni provenienti da uno qualunque degli indirizzi associati alle interfacce locali. La notazione \texttt{0.0.0.0} usata da \cmd{netstat} è equivalente all'asterisco utilizzato per il numero di porta, indica il valore generico, e corrisponde al valore \const{INADDR\_ANY} -definito in \file{arpa/inet.h} (vedi \ref{tab:TCP_ipv4_addr}). +definito in \headfile{arpa/inet.h} (vedi \ref{tab:TCP_ipv4_addr}). Inoltre si noti come la porta e l'indirizzo di ogni eventuale connessione esterna non sono specificati; in questo caso la \textit{socket pair} associata @@ -760,7 +760,7 @@ metodo con IPv6, in cui l'indirizzo deve necessariamente essere specificato con una struttura, perché il linguaggio C non consente l'uso di una struttura costante come operando a destra in una assegnazione. -Per questo motivo nell'header \file{netinet/in.h} è definita una variabile +Per questo motivo nell'header \headfile{netinet/in.h} è definita una variabile \macro{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 @@ -1100,8 +1100,9 @@ eventualmente ripetere la chiamata alla funzione come per l'errore di Un'altra differenza con BSD è che la funzione non fa ereditare al nuovo socket i flag del socket originale, come \const{O\_NONBLOCK},\footnote{ed in generale tutti quelli che si possono impostare con \func{fcntl}, vedi - sez.~\ref{sec:file_fcntl}.} che devono essere rispecificati ogni volta. Tutto -questo deve essere tenuto in conto se si devono scrivere programmi portabili. + sez.~\ref{sec:file_fcntl_ioctl}.} che devono essere rispecificati ogni +volta. Tutto questo deve essere tenuto in conto se si devono scrivere +programmi portabili. Il meccanismo di funzionamento di \func{accept} è essenziale per capire il funzionamento di un server: in generale infatti c'è sempre un solo socket in @@ -1221,9 +1222,9 @@ socket BSD fanno questa assunzione. \subsection{La funzione \func{close}} \label{sec:TCP_func_close} -La funzione standard Unix \func{close} (vedi sez.~\ref{sec:file_close}) che si -usa sui file può essere usata con lo stesso effetto anche sui file descriptor -associati ad un socket. +La funzione standard Unix \func{close} (vedi sez.~\ref{sec:file_open_close}) +che si usa sui file può essere usata con lo stesso effetto anche sui file +descriptor associati ad un socket. L'azione di questa funzione quando applicata a socket è di marcarlo come chiuso e ritornare immediatamente al processo. Una volta chiamata il socket @@ -1240,9 +1241,9 @@ Come per tutti i file descriptor anche per i socket viene mantenuto un numero di riferimenti, per cui se più di un processo ha lo stesso socket aperto l'emissione del FIN e la sequenza di chiusura di TCP non viene innescata fintanto che il numero di riferimenti non si annulla, questo si applica, come -visto in sez.~\ref{sec:file_sharing}, sia ai file descriptor duplicati che a -quelli ereditati dagli eventuali processi figli, ed è il comportamento che ci -si aspetta in una qualunque applicazione client/server. +visto in sez.~\ref{sec:file_shared_access}, sia ai file descriptor duplicati +che a quelli ereditati dagli eventuali processi figli, ed è il comportamento +che ci si aspetta in una qualunque applicazione client/server. Per attivare immediatamente l'emissione del FIN e la sequenza di chiusura descritta in sez.~\ref{sec:TCP_conn_term}, si può invece usare la funzione @@ -1297,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 @@ -1323,9 +1324,10 @@ disponibile fra i sorgenti allegati alla guida nei file \file{FullRead.c} e Come si può notare le due funzioni ripetono la lettura/scrittura in un ciclo fino all'esaurimento del numero di byte richiesti, in caso di errore viene -controllato se questo è \errcode{EINTR} (cioè un'interruzione della system -call dovuta ad un segnale), nel qual caso l'accesso viene ripetuto, altrimenti -l'errore viene ritornato al programma chiamante, interrompendo il ciclo. +controllato se questo è \errcode{EINTR} (cioè un'interruzione della +\textit{system call} dovuta ad un segnale), nel qual caso l'accesso viene +ripetuto, altrimenti l'errore viene ritornato al programma chiamante, +interrompendo il ciclo. Nel caso della lettura, se il numero di byte letti è zero, significa che si è arrivati alla fine del file (per i socket questo significa in genere che @@ -1383,7 +1385,7 @@ il numero della porta del servizio. Il primo passo (\texttt{\small 20}) è inizializzare tutto a zero, per poi inserire il tipo di indirizzo (\texttt{\small 21}) e la porta (\texttt{\small 22}), usando per quest'ultima la funzione \func{htons} per convertire il formato dell'intero usato dal -computer a quello usato nella rete, infine \texttt{\small 23--27} si può +computer a quello usato nella rete, infine (\texttt{\small 23--27}) si può utilizzare la funzione \func{inet\_pton} per convertire l'indirizzo numerico passato dalla linea di comando. @@ -2060,11 +2062,11 @@ all'esempio illustrato in fig.~\ref{fig:TCP_echo_server_first_code}. In questo modo però si introduce un altro problema. Si ricordi infatti che, come spiegato in sez.~\ref{sec:sig_gen_beha}, quando un programma si trova in -stato di \texttt{sleep} durante l'esecuzione di una system call, questa viene -interrotta alla ricezione di un segnale. Per questo motivo, alla fine -dell'esecuzione del gestore del segnale, se questo ritorna, il programma -riprenderà l'esecuzione ritornando dalla system call interrotta con un errore -di \errcode{EINTR}. +stato di \texttt{sleep} durante l'esecuzione di una \textit{system call}, +questa viene interrotta alla ricezione di un segnale. Per questo motivo, alla +fine dell'esecuzione del gestore del segnale, se questo ritorna, il programma +riprenderà l'esecuzione ritornando dalla \textit{system call} interrotta con +un errore di \errcode{EINTR}. Vediamo allora cosa comporta tutto questo nel nostro caso: quando si chiude il client, il processo figlio che gestisce la connessione terminerà, ed il padre, @@ -2081,13 +2083,13 @@ accept error: Interrupted system call \end{verbatim}%# Come accennato in sez.~\ref{sec:sig_gen_beha} le conseguenze di questo -comportamento delle system call possono essere superate in due modi diversi, -il più semplice è quello di modificare il codice di \func{Signal} per -richiedere il riavvio automatico delle system call interrotte secondo la -semantica di BSD, usando l'opzione \const{SA\_RESTART} di \func{sigaction}; -rispetto a quanto visto in fig.~\ref{fig:sig_Signal_code}. Definiremo allora la -nuova funzione \func{SignalRestart}\footnote{anche questa è definita, insieme - alle altre funzioni riguardanti la gestione dei segnali, nel file +comportamento delle \textit{system call} possono essere superate in due modi +diversi, il più semplice è quello di modificare il codice di \func{Signal} per +richiedere il riavvio automatico delle \textit{system call} interrotte secondo +la semantica di BSD, usando l'opzione \const{SA\_RESTART} di \func{sigaction}; +rispetto a quanto visto in fig.~\ref{fig:sig_Signal_code}. Definiremo allora +la nuova funzione \func{SignalRestart}\footnote{anche questa è definita, + insieme alle altre funzioni riguardanti la gestione dei segnali, nel file \file{SigHand.c}, il cui contento completo può essere trovato negli esempi allegati.} come mostrato in fig.~\ref{fig:sig_SignalRestart_code}, ed installeremo il gestore usando quest'ultima. @@ -2099,30 +2101,30 @@ installeremo il gestore usando quest'ultima. \end{minipage} \normalsize \caption{La funzione \func{SignalRestart}, che installa un gestore di - segnali in semantica BSD per il riavvio automatico delle system call - interrotte.} + segnali in semantica BSD per il riavvio automatico delle \textit{system + call} interrotte.} \label{fig:sig_SignalRestart_code} \end{figure} Come si può notare questa funzione è identica alla precedente \func{Signal}, -illustrata in fig.~\ref{fig:sig_Signal_code}, solo che in questo caso invece di -inizializzare a zero il campo \var{sa\_flags} di \struct{sigaction}, lo si +illustrata in fig.~\ref{fig:sig_Signal_code}, solo che in questo caso invece +di inizializzare a zero il campo \var{sa\_flags} di \struct{sigaction}, lo si inizializza (\texttt{\small 5}) al valore \const{SA\_RESTART}. Usando questa funzione al posto di \func{Signal} nel server non è necessaria nessuna altra -modifica: le system call interrotte saranno automaticamente riavviate, e -l'errore \errcode{EINTR} non si manifesterà più. +modifica: le \textit{system call} interrotte saranno automaticamente +riavviate, e l'errore \errcode{EINTR} non si manifesterà più. La seconda soluzione è più invasiva e richiede di controllare tutte le volte -l'errore restituito dalle varie system call, ripetendo la chiamata qualora -questo corrisponda ad \errcode{EINTR}. Questa soluzione ha però il pregio -della portabilità, infatti lo standard POSIX dice che la funzionalità di -riavvio automatico delle system call, fornita da \const{SA\_RESTART}, è -opzionale, per cui non è detto che essa sia disponibile su qualunque sistema. -Inoltre in certi casi,\footnote{Stevens in \cite{UNP1} accenna che la maggior - parte degli Unix derivati da BSD non fanno ripartire \func{select}; altri - non riavviano neanche \func{accept} e \func{recvfrom}, cosa che invece nel - caso di Linux viene sempre fatta.} anche quando questa è presente, non è -detto possa essere usata con \func{accept}. +l'errore restituito dalle varie \textit{system call}, ripetendo la chiamata +qualora questo corrisponda ad \errcode{EINTR}. Questa soluzione ha però il +pregio della portabilità, infatti lo standard POSIX dice che la funzionalità +di riavvio automatico delle \textit{system call}, fornita da +\const{SA\_RESTART}, è opzionale, per cui non è detto che essa sia disponibile +su qualunque sistema. Inoltre in certi casi,\footnote{Stevens in \cite{UNP1} + accenna che la maggior parte degli Unix derivati da BSD non fanno ripartire + \func{select}; altri non riavviano neanche \func{accept} e \func{recvfrom}, + cosa che invece nel caso di Linux viene sempre fatta.} anche quando questa è +presente, non è detto possa essere usata con \func{accept}. La portabilità nella gestione dei segnali però viene al costo di una @@ -2158,7 +2160,7 @@ programma. \normalsize \caption{La sezione nel codice della seconda versione del server per il servizio \textit{echo} modificata per tener conto dell'interruzione - delle system call.} + delle \textit{system call}.} \label{fig:TCP_echo_server_code_second} \end{figure} @@ -2180,12 +2182,12 @@ eventuale pausa con una condizione (\texttt{\small 21}) sulla variabile numero di secondi da aspettare (il valore preimpostato è nullo). Si è potuto lasciare inalterata tutta la sezione di creazione del socket -perché nel server l'unica chiamata ad una system call lenta, che può essere -interrotta dall'arrivo di \signal{SIGCHLD}, è quella ad \func{accept}, che è -l'unica funzione che può mettere il processo padre in stato di sleep nel +perché nel server l'unica chiamata ad una \textit{system call} lenta, che può +essere interrotta dall'arrivo di \signal{SIGCHLD}, è quella ad \func{accept}, +che è l'unica funzione che può mettere il processo padre in stato di sleep nel periodo in cui un figlio può terminare; si noti infatti come le altre -\index{system~call~lente} \textit{slow system call}\footnote{si ricordi la - distinzione fatta in sez.~\ref{sec:sig_gen_beha}.} o sono chiamate prima di +\index{system~call~lente} \textit{system call} lente (si ricordi la +distinzione fatta in sez.~\ref{sec:sig_gen_beha}) o sono chiamate prima di entrare nel ciclo principale, quando ancora non esistono processi figli, o sono chiamate dai figli stessi e non risentono di \signal{SIGCHLD}. @@ -2397,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 @@ -2465,15 +2467,16 @@ avanti in sez.~\ref{sec:TCP_shutdown} la chiusura di un solo capo di un socket è una operazione lecita, per cui la nostra scrittura avrà comunque successo (come si può constatare lanciando usando \cmd{strace}\footnote{il comando \cmd{strace} è un comando di debug molto utile che prende come argomento un - altro comando e ne stampa a video tutte le invocazioni di una system call, - coi relativi argomenti e valori di ritorno, per cui usandolo in questo - contesto potremo verificare che effettivamente la \func{write} ha scritto la - riga, che in effetti è stata pure trasmessa via rete.}), in quanto il nostro -programma non ha a questo punto alcun modo di sapere che dall'altra parte non -c'è più nessuno processo in grado di leggere quanto scriverà. Questo sarà -chiaro solo dopo il tentativo di scrittura, e la ricezione del segmento RST di -risposta che indica che dall'altra parte non si è semplicemente chiuso un capo -del socket, ma è completamente terminato il programma. + altro comando e ne stampa a video tutte le invocazioni di una \textit{system + call}, coi relativi argomenti e valori di ritorno, per cui usandolo in + questo contesto potremo verificare che effettivamente la \func{write} ha + scritto la riga, che in effetti è stata pure trasmessa via rete.}), in +quanto il nostro programma non ha a questo punto alcun modo di sapere che +dall'altra parte non c'è più nessuno processo in grado di leggere quanto +scriverà. Questo sarà chiaro solo dopo il tentativo di scrittura, e la +ricezione del segmento RST di risposta che indica che dall'altra parte non si +è semplicemente chiuso un capo del socket, ma è completamente terminato il +programma. Per questo motivo il nostro client proseguirà leggendo dal socket, e dato che questo è stato chiuso avremo che, come spiegato in @@ -2488,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 @@ -2769,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) è @@ -3143,7 +3147,7 @@ velocità consentitagli dalla rete, sul socket. Dato che la connessione è con una macchina remota occorre un certo tempo perché i pacchetti vi arrivino, vengano processati, e poi tornino indietro. Considerando trascurabile il tempo di processo, questo tempo è quello impiegato nella trasmissione via rete, che -viene detto RTT (dalla denominazione inglese \itindex{Round~Trip~Time} +viene detto RTT (dalla denominazione inglese \itindex{Round~Trip~Time~(RTT)} \textit{Round Trip Time}) ed è quello che viene stimato con l'uso del comando \cmd{ping}. @@ -3302,17 +3306,17 @@ con il ciclo (\texttt{\small 8--10}) in cui si impostano i socket trovati attivi. Per far questo si usa la caratteristica dei file descriptor, descritta in -sez.~\ref{sec:file_open}, per cui il kernel associa sempre ad ogni nuovo file -il file descriptor con il valore più basso disponibile. Questo fa sì che si -possa eseguire il ciclo (\texttt{\small 8}) a partire da un valore minimo, che -sarà sempre quello del socket in ascolto, mantenuto in \var{list\_fd}, fino al -valore massimo di \var{max\_fd} che dovremo aver cura di tenere aggiornato. -Dopo di che basterà controllare (\texttt{\small 9}) nella nostra tabella se il -file descriptor è in uso o meno,\footnote{si tenga presente che benché il - kernel assegni sempre il primo valore libero, dato che nelle operazioni i - socket saranno aperti e chiusi in corrispondenza della creazione e - conclusione delle connessioni, si potranno sempre avere dei \textsl{buchi} - nella nostra tabella.} e impostare \var{fset} di conseguenza. +sez.~\ref{sec:file_open_close}, per cui il kernel associa sempre ad ogni nuovo +file il file descriptor con il valore più basso disponibile. Questo fa sì che +si possa eseguire il ciclo (\texttt{\small 8}) a partire da un valore minimo, +che sarà sempre quello del socket in ascolto, mantenuto in \var{list\_fd}, +fino al valore massimo di \var{max\_fd} che dovremo aver cura di tenere +aggiornato. Dopo di che basterà controllare (\texttt{\small 9}) nella nostra +tabella se il file descriptor è in uso o meno,\footnote{si tenga presente che + benché il kernel assegni sempre il primo valore libero, dato che nelle + operazioni i socket saranno aperti e chiusi in corrispondenza della + creazione e conclusione delle connessioni, si potranno sempre avere dei + \textsl{buchi} nella nostra tabella.} e impostare \var{fset} di conseguenza. Una volta inizializzato con i socket aperti il nostro \textit{file descriptor set} potremo chiamare \func{select} per fargli osservare lo stato degli @@ -3576,7 +3580,7 @@ sez.~\ref{sec:TCP_serv_select}. -\subsection{I/O multiplexing con \func{epoll}} +\subsection{I/O multiplexing con \textit{epoll}} \label{sec:TCP_serv_epoll} Da fare.