Ultimo materiale, rivisto HTML del sito, e iniziato a parlare di select +
authorSimone Piccardi <piccardi@gnulinux.it>
Sun, 21 Sep 2003 18:41:27 +0000 (18:41 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sun, 21 Sep 2003 18:41:27 +0000 (18:41 +0000)
socket

fileadv.tex
html/gapil.html
tcpsock.tex
tcpsockadv.tex

index ce328748c716953330fa39a6385250fd58066c41..445d9c73fd613ef378ab181d1ed7924cc6d79a0e 100644 (file)
@@ -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
index d66a73be327e93cf78bf0f5feef755d57a8b3828..7024ee80d5b780f94bc9ec9adb2f8e06c5484f30 100644 (file)
                <tr>
                  <td valign="top"> <b> Cap. 10 </b> </td>
                  <td valign="top"> Sessioni e terminali</td> 
-                 <td valign="top"> Sessioni complete, da revisionare, 
+                 <td valign="top"> sessioni complete, da revisionare, 
                    terminali quasi completi. </td>
                </tr>
                <tr>
                <tr>
                  <td valign="top"> <b> Cap. 12 </b> </td>
                  <td valign="top"> IPC </td> 
-                 <td valign="top"> Pipe, fifo e code, semafori, 
+                 <td valign="top"> pipe, fifo e code, semafori, 
                    memoria condivisa, tecniche alternative completi, da
                    revisionare, IPC POSIX quasi completo. 
                  </td>
                </tr>
                <tr>
-                 <td valign="top"> <b> Cap. 13-14 </b> </td>
+                 <td valign="top"> <b> Cap. 13 </b> </td>
                  <td valign="top"> Introduzione alla rete</td> 
-                 <td valign="top"> completi, da revisionare </td>
+                 <td valign="top"> completo, da revisionare </td>
+               </tr>
+               <tr>
+                 <td valign="top"> <b> Cap. 14 </b> </td>
+                 <td valign="top"> I socket</td> 
+                 <td valign="top"> completo, da revisionare. Manca la
+                 trattazione di eventuali ulteriori famiglie. </td>
                </tr>
                <tr>
                  <td valign="top"> <b> Cap. 15-16 </b> </td>
-                 <td valign="top"> Socket TCP elementari</td> 
-                 <td valign="top"> Caratteristiche base quasi complete,
-                   esempio elementare da concludere </td>
+                 <td valign="top"> I socket TCP </td> 
+                 <td valign="top"> socket TCP elementari completo, da
+                   revisionare. Socket TCP avanzati appena iniziato,
+                   in fase di stesura.
+
+                 </td>
+               </tr>
+               <tr>
+                 <td valign="top"> <b> Appendici </b> </td>
+                 <td valign="top"> I protocolli, gli errori, ecc.</td> 
+                 <td valign="top"> Materiale messo insieme alla
+                 rinfusa, e da rivedere da zero.
+                 </td>
                </tr>
              </tbody>
            </table>
            <p>
-             <b> Versione corrente:</b> 473 pagine.
+             <b> Versione corrente:</b> 485 pagine.
            </p>
          </td>
        </tr>
            </b>
          </td>
          <td bgcolor="lightblue"> 
+
+             <b>21 - settembre - 2003</b> <br/> 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.
            <p>
              <b>6 - aprile - 2003</b> <br/> Grazie all'incredibile lavoro di
              Mirko Maischberger abbiamo una favolosa versione in HTML, che
index 63b97438411db9afb5dc08415f464f0948f2b53b..ae53fd0d1dc7585b0451710636820d80484c0772 100644 (file)
@@ -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.
 
 
 
index 81c37eb5bc981d8f912ea56cdb414f7e10634040..24c45d2cbf9d1aa707fec08f248fbb4e5703530e 100644 (file)
@@ -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.