From fcd431ebcd9f7a65680a669a2740ef5a2586531c Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 21 Sep 2003 18:41:27 +0000 Subject: [PATCH] Ultimo materiale, rivisto HTML del sito, e iniziato a parlare di select + socket --- fileadv.tex | 43 ++++++++++--------- html/gapil.html | 37 ++++++++++++---- tcpsock.tex | 17 ++++---- tcpsockadv.tex | 109 +++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 153 insertions(+), 53 deletions(-) diff --git a/fileadv.tex b/fileadv.tex index ce32874..445d9c7 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -192,12 +192,11 @@ rimanente.\footnote{questo pu Uno dei problemi che si presentano con l'uso di \func{select} è che il suo comportamento dipende dal valore del file descriptor che si vuole tenere sotto -controllo. Infatti il kernel riceve solo un valore massimo, e dovrà -effettuare una scansione su tutto l'intervallo, che può essere anche molto -ampio, per capire quali sono i file descriptor da tenere sotto controllo, -anche se sono solo poche unità; e questo ha ovviamente un pessimo risultato -per le prestazioni; il comportamenento viene della funzione viene così a -dipendere in maniera innaturale dal valore del file decriptor. +controllo. Infatti il kernel riceve con \param{n} un valore massimo per tale +valore, e per capire quali sono i file descriptor da tenere sotto controllo +dovrà effettuare una scansione su tutto l'intervallo, che può anche essere +anche molto ampio anche se i file descriptor sono solo poche unità; tutto ciò +ha ovviamente delle conseguenze ampiamente negative per le prestazioni. Inoltre c'è anche il problema che il numero massimo dei file che si possono tenere sotto controllo, la funzione è nata quando il kernel consentiva un @@ -256,27 +255,27 @@ vengono utilizzati solo per \var{revents} come valori in uscita). \begin{table}[htb] \centering \footnotesize - \begin{tabular}[c]{|l|c|l|} + \begin{tabular}[c]{|l|l|} \hline - \textbf{Flag} & \textbf{Valore} & \textbf{Significato} \\ + \textbf{Flag} & \textbf{Significato} \\ \hline \hline - \const{POLLIN} & 0x001 & È possibile la lettura immediata.\\ - \const{POLLPRI} & 0x002 & Sono presenti dati urgenti.\\ - \const{POLLOUT} & 0x004 & È possibile la scrittura immediata.\\ + \const{POLLIN} & È possibile la lettura immediata.\\ + \const{POLLPRI} & Sono presenti dati urgenti.\\ + \const{POLLOUT} & È possibile la scrittura immediata.\\ \hline - \const{POLLERR} & 0x008 & C'è una condizione di errore.\\ - \const{POLLHUP} & 0x010 & Si è verificato un hung-up.\\ - \const{POLLNVAL} & 0x020 & Il file descriptor non è aperto.\\ + \const{POLLERR} & C'è una condizione di errore.\\ + \const{POLLHUP} & Si è verificato un hung-up.\\ + \const{POLLNVAL} & Il file descriptor non è aperto.\\ \hline - \const{POLLRDNORM}& 0x040 & Sono disponibili in lettura dati normali.\\ - \const{POLLRDBAND}& 0x080 & Sono disponibili in lettura dati ad alta - priorità. \\ - \const{POLLWRNORM}& 0x100 & È possibile la scrittura di dati normali. \\ - \const{POLLWRBAND}& 0x200 & È possibile la scrittura di dati ad - alta priorità. \\ - \const{POLLMSG} & 0x400 & Un segnale \const{SIGPOLL} è arrivato alla - cima dello stream.\\ + \const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\ + \const{POLLRDBAND}& Sono disponibili in lettura dati ad alta + priorità. \\ + \const{POLLWRNORM}& È possibile la scrittura di dati normali. \\ + \const{POLLWRBAND}& È possibile la scrittura di dati ad + alta priorità. \\ + \const{POLLMSG} & Un segnale \const{SIGPOLL} è arrivato alla + cima dello stream (non usato).\\ \hline \end{tabular} \caption{Costanti per l'identificazione dei vari bit dei campi diff --git a/html/gapil.html b/html/gapil.html index d66a73b..7024ee8 100644 --- a/html/gapil.html +++ b/html/gapil.html @@ -202,7 +202,7 @@ Cap. 10 Sessioni e terminali - Sessioni complete, da revisionare, + sessioni complete, da revisionare, terminali quasi completi. @@ -217,26 +217,42 @@ Cap. 12 IPC - Pipe, fifo e code, semafori, + pipe, fifo e code, semafori, memoria condivisa, tecniche alternative completi, da revisionare, IPC POSIX quasi completo. - Cap. 13-14 + Cap. 13 Introduzione alla rete - completi, da revisionare + completo, da revisionare + + + Cap. 14 + I socket + completo, da revisionare. Manca la + trattazione di eventuali ulteriori famiglie. Cap. 15-16 - Socket TCP elementari - Caratteristiche base quasi complete, - esempio elementare da concludere + I socket TCP + socket TCP elementari completo, da + revisionare. Socket TCP avanzati appena iniziato, + in fase di stesura. + + + + + Appendici + I protocolli, gli errori, ecc. + Materiale messo insieme alla + rinfusa, e da rivedere da zero. +

- Versione corrente: 473 pagine. + Versione corrente: 485 pagine.

@@ -249,6 +265,11 @@ + + 21 - settembre - 2003
Completato il capitolo sui + socket elementari, e corretti numerosi errori. Revisione della + sezione sull'I/O multiplexing nel capitolo sui file avanzati in + vista dell'uso nel capitolo sui socket TCP avanzati.

6 - aprile - 2003
Grazie all'incredibile lavoro di Mirko Maischberger abbiamo una favolosa versione in HTML, che diff --git a/tcpsock.tex b/tcpsock.tex index 63b9743..ae53fd0 100644 --- a/tcpsock.tex +++ b/tcpsock.tex @@ -221,7 +221,7 @@ chiusura attiva. Nella sequenza indicata i dati verrebbero persi, dato che si è chiuso il socket dal lato che esegue la chiusura attiva; esistono tuttavia situazioni in cui si vuole poter sfruttare questa possibilità, usando una procedura che è chiamata \textit{half-close}; torneremo su questo aspetto e su -come utilizzarlo in \secref{xxx_shutdown}, quando parleremo della funzione +come utilizzarlo in \secref{sec:TCP_shutdown}, quando parleremo della funzione \func{shutdown}. La emissione del FIN avviene quando il socket viene chiuso, questo però non @@ -339,8 +339,8 @@ 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. +IP (per maggiori dettagli vedi \secref{sec:ip_protocol}), 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 @@ -1034,8 +1034,8 @@ funzione. Se non ci sono connessioni pendenti da accettare la funzione 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 -una. + operazione in \secref{sec:TCP_sock_multiplexing}.} fintanto che non ne +arriva una. La funzione può essere usata solo con socket che supportino la connessione (cioè di tipo \const{SOCK\_STREAM}, \const{SOCK\_SEQPACKET} o @@ -1202,7 +1202,7 @@ si aspetta in una qualunque applicazione client/server. Per attivare immediatamente l'emissione del FIN e la sequenza di chiusura descritta in \secref{sec:TCP_conn_term}, si può invece usare la funzione \func{shutdown} su cui torneremo in seguito (vedi -\secref{sec:TCP_xxx_shutdown}). +\secref{sec:TCP_shutdown}). @@ -2384,7 +2384,7 @@ definitiva della connessione anche nel client, dove non comparir nell'output di \cmd{netstat}. Come abbiamo accennato in \secref{sec:TCP_conn_term} e come vedremo più avanti -in \secref{sec:TCP_xxx_shutdown} la chiusura di un solo capo di un socket è +in \secref{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 parametro un @@ -2657,7 +2657,8 @@ riportando appunto come errore \errcode{ECONNRESET}. Occorre precisare che se si vuole che il client sia in grado di accorgersi del crollo del server anche quando non sta effettuando uno scambio di dati, è possibile usare una impostazione speciale del socket (ci torneremo in -\secref{sec:TCP_xxx_sockopt}) che provvede all'esecuzione di questo controllo. +\secref{sec:TCP_sock_options}) che provvede all'esecuzione di questo +controllo. diff --git a/tcpsockadv.tex b/tcpsockadv.tex index 81c37eb..24c45d2 100644 --- a/tcpsockadv.tex +++ b/tcpsockadv.tex @@ -35,25 +35,103 @@ riprenderemo l'argomento in questa sezione. -\subsection{La funzione \func{select} con i socket.} +\subsection{Il comportamento della funzione \func{select} con i socket.} \label{sec:TCP_sock_select} - - - Iniziamo con la prima delle funzioni usate per l'I/O multiplexing, \func{select}, il suo funzionamento è già stato descritto in dettaglio in -\secref{sec:file_multiplexing}; e sappiamo che la funzione ritorna quando uno -o più dei file descriptor messi sotto controllo è pronto per la relativa -operazione. +\secref{sec:file_multiplexing} e non staremo a ripetere quanto detto lì; +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 se per dei normali file, o anche per delle pipe, la condizione di -essere pronti per la lettura o la scrittura è ovvia, lo è un po' meno di meno -nel caso dei socket, visto che intervengono tutte le possibili condizioni -dovute alla rete. Occorre allora specificare quali sono le condizioni in cui -un socket risulta \textsl{pronto}. - +infatti per dei normali file, o anche per delle pipe, la condizione di essere +pronti per la lettura o la scrittura è ovvia, lo è un po' meno di meno nel +caso dei socket, visto che intervengono tutte le possibili condizioni dovute +alla rete. Occorre allora specificare quali sono le condizioni in cui un +socket risulta \textsl{pronto} quando viene passato come membro di uno dei tre +\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) è +pronto per la lettura sono le seguenti: +\begin{itemize*} +\item nel buffer di ricezione del socket sono arrivati dei dati in quantità + sufficiente a superare il valore di una \textsl{soglia di basso livello} (il + cosiddetto \textit{low watermark}). Questo valore è espresso in numero di + byte e può essere impostato con l'opzione del socket \const{SO\_RCVLOWAT} + (tratteremo le opzioni dei socket in \secref{sec:TCP_sock_options}); il suo + valore di default è 1 per i socket TCP e UDP. In questo caso una operazione + di lettura avrà successo e leggerà un numero di byte maggiore di zero. +\item il lato in lettura della connessione è stato chiuso; si è cioè ricevuto + un segmento FIN (si ricordi quanto illustrato in \secref{sec:TCP_conn_term}) + sulla connessione. In questo caso una operazione di lettura avrà successo, + ma non risulteranno presenti dati (in sostanza \func{read} ritornerà con un + valore nullo) per indicare la condizione di end-of-file. +\item c'è stato un errore sul socket. In questo caso una operazione di lettura + non si bloccherà ma restituirà una condizione di errore (ad esempio + \func{read} restituirà -1) e imposterà la variabile \var{errno} al relativo + valore. Vedremo in \secref{sec:TCP_sock_options} come sia possibile estrarre + e cancellare errori pendenti su un socket usando l'opzione + \const{SO\_ERROR}. +\item quando si sta utilizzando un \textit{listening socket} ed ci sono delle + connessioni completate. In questo caso la funzione \func{accept} non si + bloccherà.\footnote{in realtà questo non è sempre vero, come accennato in + \secref{sec:TCP_conn_early_abort} una connessione può essere abortita + dalla ricezione di un segmento RST una volta che è stata completata, + allora se questo avviene dopo che \func{select} è ritornata, ma prima + della chiamata ad \func{accept} quest'ultima, in assenza di altre + connessiioni, potrà bloccarsi.} +\end{itemize*} + +Le condizioni che fanno si che la funzione \func{select} ritorni segnalando +che un socket (che sarà riportato nel secondo insieme di file descriptor) è +pronto per la scrittura sono le seguenti: +\begin{itemize*} +\item nel buffer di invio è disponibile una quantità di spazio superiore al + valore della \textsl{soglia di basso livello} in scrittura ed inoltre o il + socket è già connesso o non necessita (ad esempio è UDP) di connessione. Il + valore della soglia è espresso in numero di byte e può essere impostato con + l'opzione del socket \const{SO\_SNDLOWAT}; il suo valore di default è 2048 + per i socket TCP e UDP. In questo caso una operazione di scrittura non si + bloccherà e restituirà un valore positivo pari al numero di byte accettati + dal livello di trasporto. +\item il lato in scrittura della connessione è stato chiuso. In questo caso + una operazione di scrittura sul socket genererà il segnale \const{SIGPIPE}. +\item c'è stato un errore sul socket. In questo caso una operazione di + scrittura non si bloccherà ma restituirà una condizione di errore ed + imposterà opportunamente la variabile \var{errno}. Vedremo in + \secref{sec:TCP_sock_options} come sia possibile estrarre e cancellare + errori pendenti su un socket usando l'opzione \const{SO\_ERROR}. +\end{itemize*} + +Infine c'è una sola condizione che fa si che \func{select} ritorni segnalando +che un socket (che sarà riportato nel terzo insieme di file descriptor) ha una +condizione di eccezione pendente, e cioè la ricezione sul socket di dati +\textsl{fuori banda} (o \textit{out-of-band}), una caratteristica specifica +dei socket TCP su cui torneremo in \secref{sec:TCP_outofband}. + +Si noti come nel caso della lettura \func{select} si applichi anche ad +operazioni che non hanno nulla a che fare con l'I/O come il riconoscimento +della presenza di connessioni pronte, in modo da consentire l'utilizzo di +\func{accept} in modalità non bloccante. Si noti infine come in caso di errore +un socket venga sempre riportato come pronto sia per la lettura che per la +scrittura. + +Lo scopo dei due valori di soglia per i buffer di ricezione e di invio è +quello di consentire maggiore flessibilità nell'uso di \func{select} da parte +dei programmi, se infatti si sa che una applicazione non è in grado di fare +niente fintanto che non può ricevere o inviare una certa quantità di dati, si +possono utilizzare questi valori per far si che \func{select} ritorni solo +quando c'è la certezza di avere dati a sufficienza.\footnote{questo tipo di + controllo è utile di norma solo per la lettura, in quanto in genere le + operazioni di scrittura sono già controllate dall'applicazione, che sà + sempre quanti dati invia, mentre non è detto possa conoscere la quantità di + dati in ricezione; per cui, nella situazione in cui si conosce almeno un + valore minimo, per evitare la penalizzazione dovuta alla ripetizione delle + operazioni di lettura quando per accumulare dati sufficienti, si può + lasciare al kernel il compito di impostare un minimo al di sotto del quale + il file descriptor, pur avendo disponibili dei dati, non viene letto.} @@ -62,8 +140,9 @@ un socket risulta \textsl{pronto}. \label{sec:TCP_sock_options} Dato che la maggior parte delle opzioni dei socket sono relative ai socket -TCP, ed hanno poi significato analogo quando usate con altri socket, -tratteremo qui l'argomento in generale. +TCP, ed hanno poi significato analogo quando usate con altri socket, abbiamo +preferito trattare l'argomento in generale in questa sezione piuttosto che +nel capitolo dedicato alla trattazione generica dei socket. -- 2.30.2