alle funzioni presenti nelle due strutture \kstruct{inode\_operation} e
\kstruct{file\_operation}. Ovviamente non è detto che tutte le operazioni
possibili siano poi disponibili in tutti i casi, ad esempio \code{llseek} non
-sarà presente per un dispositivo come la porta seriale o per una fifo, mentre
-sui file del filesystem \texttt{vfat} non saranno disponibili i permessi, ma
-resta il fatto che grazie al VFS le \textit{system call} per le operazioni sui
-file possono restare sempre le stesse nonostante le enormi differenze che
-possono esserci negli oggetti a cui si applicano.
+sarà presente per un dispositivo come la porta seriale o per una
+\textit{fifo}, mentre sui file del filesystem \texttt{vfat} non saranno
+disponibili i permessi, ma resta il fatto che grazie al VFS le \textit{system
+ call} per le operazioni sui file possono restare sempre le stesse nonostante
+le enormi differenze che possono esserci negli oggetti a cui si applicano.
\itindend{Virtual~File~System~(VFS)}
directory che lo contiene e decrementa il numero di riferimenti nel relativo
\textit{inode}.\footnote{come per \func{link} queste due operazioni sono
effettuate all'interno della \textit{system call} in maniera atomica.} Nel
-caso di socket, fifo o file di dispositivo rimuove il nome, ma come per i file
-normali i processi che hanno aperto uno di questi oggetti possono continuare
-ad utilizzarli. Nel caso di cancellazione di un collegamento simbolico, che
-consiste solo nel rimando ad un altro file, questo viene immediatamente
-eliminato.
+caso di socket, \textit{fifo} o file di dispositivo rimuove il nome, ma come
+per i file normali i processi che hanno aperto uno di questi oggetti possono
+continuare ad utilizzarli. Nel caso di cancellazione di un collegamento
+simbolico, che consiste solo nel rimando ad un altro file, questo viene
+immediatamente eliminato.
Per cancellare una voce in una directory è necessario avere il permesso di
scrittura su di essa, dato che si va a rimuovere una voce dal suo contenuto, e
della stringa.
Per quanto riguarda il significato dei campi opzionali, il campo \var{d\_type}
-indica il tipo di file (se fifo, directory, collegamento simbolico, ecc.), e
-consente di evitare una successiva chiamata a \func{lstat} (vedi
+indica il tipo di file (se \textit{fifo}, directory, collegamento simbolico,
+ecc.), e consente di evitare una successiva chiamata a \func{lstat} (vedi
sez.~\ref{sec:file_stat}) per determinarlo. I suoi possibili valori sono
riportati in tab.~\ref{tab:file_dtype_macro}. Si tenga presente che questo
valore è disponibile solo per i filesystem che ne supportano la restituzione
\constd{DT\_REG} & File normale.\\
\constd{DT\_DIR} & Directory.\\
\constd{DT\_LNK} & Collegamento simbolico.\\
- \constd{DT\_FIFO} & Fifo.\\
+ \constd{DT\_FIFO} & \textit{Fifo}.\\
\constd{DT\_SOCK} & Socket.\\
\constd{DT\_CHR} & Dispositivo a caratteri.\\
\constd{DT\_BLK} & Dispositivo a blocchi.\\
Finora abbiamo parlato esclusivamente di file, directory e collegamenti
simbolici, ma in sez.~\ref{sec:file_file_types} abbiamo visto che il sistema
prevede anche degli altri tipi di file, che in genere vanno sotto il nome
-generico di \textsl{file speciali}, come i file di dispositivo, le fifo ed i
+generico di \textsl{file speciali}, come i file di dispositivo, le \textit{fifo} ed i
socket.
La manipolazione delle caratteristiche di questi file speciali, il cambiamento
\item[\errcode{EEXIST}] \param{pathname} esiste già o è un collegamento
simbolico.
\item[\errcode{EINVAL}] il valore di \param{mode} non indica un file, una
- fifo, un socket o un dispositivo.
+ \textit{fifo}, un socket o un dispositivo.
\item[\errcode{EPERM}] non si hanno privilegi sufficienti a creare
l'\texttt{inode}, o il filesystem su cui si è cercato di
creare \param{pathname} non supporta l'operazione.
\const{S\_IFREG} per un file regolare (che sarà creato vuoto),
\const{S\_IFBLK} per un dispositivo a blocchi, \const{S\_IFCHR} per un
dispositivo a caratteri, \const{S\_IFSOCK} per un socket e \const{S\_IFIFO}
-per una fifo;\footnote{con Linux la funzione non può essere usata per creare
- directory o collegamenti simbolici, si dovranno usare le funzioni
+per una \textit{fifo};\footnote{con Linux la funzione non può essere usata per
+ creare directory o collegamenti simbolici, si dovranno usare le funzioni
\func{mkdir} e \func{symlink} a questo dedicate.} un valore diverso
comporterà l'errore \errcode{EINVAL}. Inoltre \param{pathname} non deve
esistere, neanche come collegamento simbolico.
mentre è presente in SVr4 e 4.4BSD, ma esistono differenze nei comportamenti
e nei codici di errore, tanto che questa è stata introdotta in POSIX.1-2001
con una nota che la definisce portabile solo quando viene usata per creare
- delle fifo, ma comunque deprecata essendo utilizzabile a tale scopo la
- specifica \func{mkfifo}.} l'uso per la creazione di un file ordinario, di
-una fifo o di un socket è consentito anche agli utenti normali.
+ delle \textit{fifo}, ma comunque deprecata essendo utilizzabile a tale scopo
+ la specifica \func{mkfifo}.} l'uso per la creazione di un file ordinario, di
+una \textit{fifo} o di un socket è consentito anche agli utenti normali.
I nuovi \textit{inode} creati con \func{mknod} apparterranno al proprietario e
al gruppo del processo (usando \ids{UID} e \ids{GID} del gruppo effettivo) che
Dato che la funzione di sistema \func{mknod} presenta diverse varianti nei
vari sistemi unix-like, lo standard POSIX.1-2001 la dichiara portabile solo in
-caso di creazione delle fifo, ma anche in questo caso alcune combinazioni
-degli argomenti restano non specificate, per cui nello stesso standard è stata
-introdotta una funzione specifica per creare una fifo deprecando l'uso di
-\func{mknod} a tale riguardo. La funzione è \funcd{mkfifo} ed il suo
-prototipo è:
+caso di creazione delle \textit{fifo}, ma anche in questo caso alcune
+combinazioni degli argomenti restano non specificate, per cui nello stesso
+standard è stata introdotta una funzione specifica per creare una
+\textit{fifo} deprecando l'uso di \func{mknod} a tale riguardo. La funzione è
+\funcd{mkfifo} ed il suo prototipo è:
\begin{funcproto}{
\fhead{sys/types.h}
\fhead{sys/stat.h}
\fdecl{int mkfifo(const char *pathname, mode\_t mode)}
-\fdesc{Crea una fifo.}
+\fdesc{Crea una \textit{fifo}.}
}
{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
caso \var{errno} assumerà \errval{EACCES}, \errval{EEXIST},
\errval{EROFS} nel loro significato generico.}
\end{funcproto}
-La funzione crea la fifo \param{pathname} con i permessi \param{mode}. Come
-per \func{mknod} il file \param{pathname} non deve esistere (neanche come
-collegamento simbolico); al solito i permessi specificati da \param{mode}
-vengono modificati dal valore di \textit{umask} (vedi
-sez.~\ref{sec:file_perm_management}).
+La funzione crea la \textit{fifo} \param{pathname} con i
+permessi \param{mode}. Come per \func{mknod} il file \param{pathname} non deve
+esistere (neanche come collegamento simbolico); al solito i permessi
+specificati da \param{mode} vengono modificati dal valore di \textit{umask}
+(vedi sez.~\ref{sec:file_perm_management}).
\index{file!speciali|)}
\macrod{S\_ISDIR}\texttt{(m)} & Directory.\\
\macrod{S\_ISCHR}\texttt{(m)} & Dispositivo a caratteri.\\
\macrod{S\_ISBLK}\texttt{(m)} & Dispositivo a blocchi.\\
- \macrod{S\_ISFIFO}\texttt{(m)} & Fifo.\\
+ \macrod{S\_ISFIFO}\texttt{(m)} & \textit{Fifo}.\\
\macrod{S\_ISLNK}\texttt{(m)} & Collegamento simbolico.\\
\macrod{S\_ISSOCK}\texttt{(m)} & Socket.\\
\hline
\constd{S\_IFBLK} & 0060000 & Dispositivo a blocchi.\\
\constd{S\_IFDIR} & 0040000 & Directory.\\
\constd{S\_IFCHR} & 0020000 & Dispositivo a caratteri.\\
- \constd{S\_IFIFO} & 0010000 & Fifo.\\
+ \constd{S\_IFIFO} & 0010000 & \textit{Fifo}.\\
\hline
\constd{S\_ISUID} & 0004000 & Set user ID (\acr{suid}) bit, vedi
sez.~\ref{sec:file_special_perm}).\\
una struttura \struct{stat} contiene la dimensione del file in byte. Questo
però è vero solo se si tratta di un file regolare, mentre nel caso di un
collegamento simbolico la dimensione è quella del \textit{pathname} che il
-collegamento stesso contiene, infine per le fifo ed i file di dispositivo
+collegamento stesso contiene, infine per le \textit{fifo} ed i file di dispositivo
questo campo è sempre nullo.
Il campo \var{st\_blocks} invece definisce la lunghezza del file in blocchi di
due casi hanno a che fare con il contenuto del file, e nella discussione
relativa all'uso degli \textit{extended user attributes} nessuno è mai stato
capace di indicare una qualche forma sensata di utilizzo degli stessi per
- collegamenti simbolici o file di dispositivo, e neanche per le fifo o i
+ collegamenti simbolici o file di dispositivo, e neanche per le \textit{fifo} o i
socket. Per questo motivo essi sono stati completamente disabilitati per
tutto ciò che non sia un file regolare o una directory.\footnote{si può
verificare la semantica adottata consultando il file \texttt{fs/xattr.c}
permette di selezionare, nel traffico di rete generato su una macchina, i
pacchetti che interessano, stampando a video (o salvando su disco) il loro
contenuto. Non staremo qui ad entrare nei dettagli dell'uso del programma, che
-sono spiegati dalla pagina di manuale; per l'uso che vogliamo farne quello che
-ci interessa è, posizionandosi sulla macchina che fa da client, selezionare
-tutti i pacchetti che sono diretti o provengono dalla macchina che fa da
-server. In questo modo (posto che non ci siano altre connessioni col server,
-cosa che avremo cura di evitare) tutti i pacchetti rilevati apparterranno alla
-nostra sessione di interrogazione del servizio.
+sono spiegati dalla pagina di manuale;\footnote{per una trattazione di base si
+ può consultare sez.~5.2.2 di \cite{SGL}.} per l'uso che vogliamo farne
+quello che ci interessa è, posizionandosi sulla macchina che fa da client,
+selezionare tutti i pacchetti che sono diretti o provengono dalla macchina che
+fa da server. In questo modo (posto che non ci siano altre connessioni col
+server, cosa che avremo cura di evitare) tutti i pacchetti rilevati
+apparterranno alla nostra sessione di interrogazione del servizio.
Il comando \cmd{tcpdump} permette selezioni molto complesse, basate sulle
interfacce su cui passano i pacchetti, sugli indirizzi IP, sulle porte, sulle
quest'ultimo, a partire dal terzo pacchetto, viene espresso in forma relativa
per maggiore compattezza. Il campo \texttt{win} in 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
sequenza di altri quattro pacchetti. Il primo, dal client al server,
contraddistinto da una lettera \texttt{P} che significa che il flag PSH è
impostato, contiene la nostra riga (che è appunto di 11 caratteri), e ad esso
-il server risponde immediatamente con un pacchetto vuoto di ricevuto. Poi
-tocca al server riscrivere indietro quanto gli è stato inviato, per cui sarà
-lui a mandare indietro un terzo pacchetto con lo stesso contenuto appena
+il server risponde immediatamente con un pacchetto vuoto di ricevuto.
+
+Poi tocca al server riscrivere indietro quanto gli è stato inviato, per cui
+sarà lui a mandare indietro un terzo pacchetto con lo stesso contenuto appena
ricevuto, e a sua volta riceverà dal client un ACK nel quarto pacchetto.
Questo causerà la ricezione dell'eco nel client che lo stamperà a video.
modo da controllare gli stati di uscita delle varie chiamate. Si è riportata
la nuova versione della funzione in fig.~\ref{fig:TCP_ClientEcho_second}.
-\begin{figure}[!htbp]
+\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{\codesamplewidth}
\includecodesample{listati/ClientEcho_second.c}
\label{sec:TCP_conn_crash}
La terminazione del server è solo uno dei possibili scenari di terminazione
-della connessione, un altro caso è ad esempio quello in cui si ha un crollo
-della rete, cosa che potremo simulare facilmente staccando il cavo di rete.
-Un'altra condizione è quella di un blocco della macchina completo della su cui
-gira il server che deve essere riavviata, cosa che potremo simulare eseguendo
-un reset fisico,\footnote{un normale shutdown non va bene; in tal caso infatti
- il sistema provvede a terminare tutti i processi, per cui la situazione
- sarebbe sostanzialmente identica alla precedente.} che, in maniera più
-gentile, riavviando la macchina dopo aver interrotto la connessione di rete.
-
-Cominciamo ad analizzare il primo caso, il crollo della rete. Ripetiamo la
-nostra sessione di lavoro precedente, lanciamo il client, scriviamo una prima
-riga, poi stacchiamo il cavo e scriviamo una seconda riga. Il risultato che
-otterremo è:
+della connessione, un altro caso è ad esempio quello in cui si ha
+un'interruzione sulla rete, cosa che potremo simulare facilmente staccando il
+cavo di rete. Un'altra condizione è quella di un blocco completo della
+macchina su cui gira il server che deve essere riavviata, cosa che potremo
+simulare sia eseguendo un reset fisico (un normale shutdown non va bene; in
+tal caso infatti il sistema provvede a terminare tutti i processi, per cui la
+situazione sarebbe sostanzialmente identica alla precedente) oppure, in
+maniera più gentile, riavviando la macchina dopo aver interrotto la
+connessione di rete.
+
+Cominciamo ad analizzare il primo caso, l'interruzione del collegamento di
+rete. Ripetiamo la nostra sessione di lavoro precedente, lanciamo il client,
+scriviamo una prima riga, poi stacchiamo il cavo e scriviamo una seconda
+riga. Il risultato che otterremo è:
\begin{Console}
[piccardi@gont sources]$ \textbf{./echo 192.168.1.141}
Prima riga
riportato alla ricezione di un pacchetto ICMP di \textit{destination
unreachable} da parte del router che individua l'interruzione della
connessione. Di nuovo anche qui il risultato finale dipende da quale è il
-meccanismo più veloce ad accorgersi del problema.
+meccanismo più veloce che porta ad accorgersi del problema.
Se però agiamo sui parametri del kernel, e scriviamo in \file{tcp\_retries2}
un valore di tentativi più basso, possiamo evitare la scadenza della
controllo.
-\section{L'uso dell'I/O multiplexing}
+\section{L'uso dell'\textit{I/O multiplexing}}
\label{sec:TCP_sock_multiplexing}
-Affronteremo in questa sezione l'utilizzo dell'I/O multiplexing, affrontato in
-sez.~\ref{sec:file_multiplexing}, nell'ambito delle applicazioni di rete. Già
-in sez.~\ref{sec:TCP_server_crash} era emerso il problema relativo al client
-del servizio echo che non era in grado di accorgersi della terminazione
-precoce del server, essendo bloccato nella lettura dei dati immessi da
-tastiera.
+Affronteremo in questa sezione l'utilizzo dell'\textit{I/O multiplexing},
+affrontato in sez.~\ref{sec:file_multiplexing}, nell'ambito delle applicazioni
+di rete. Già in sez.~\ref{sec:TCP_server_crash} era emerso il problema
+relativo al client del servizio \textit{echo} che non era in grado di
+accorgersi della terminazione precoce del server, essendo bloccato nella
+lettura dei dati immessi da tastiera.
Abbiamo visto in sez.~\ref{sec:file_multiplexing} quali sono le funzionalità
del sistema che ci permettono di tenere sotto controllo più file descriptor in
\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,
+Iniziamo con la prima delle funzioni usate per l'\textit{I/O multiplexing},
\func{select}; il suo funzionamento è già stato descritto in dettaglio in
-sez.~\ref{sec:file_multiplexing} e non staremo a ripetere quanto detto lì;
+sez.~\ref{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.
sez.~\ref{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.
+ condizione di \textit{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
+ \func{read} restituirà $-1$) e imposterà la variabile \var{errno} al relativo
valore. Vedremo in sez.~\ref{sec:sock_generic_options} come sia possibile
estrarre e cancellare gli errori pendenti su un socket senza usare
\func{read} usando l'opzione \const{SO\_ERROR}.
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} (trattata in
+ l'opzione del socket \const{SO\_SNDLOWAT} (trattata in
sez.~\ref{sec:sock_generic_options}); 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
-\subsection{Un esempio di I/O multiplexing}
+\subsection{Un esempio di \textit{I/O multiplexing}}
\label{sec:TCP_multiplex_example}
-Abbiamo incontrato la problematica tipica che conduce all'uso dell'I/O
-multiplexing nella nostra analisi degli errori in
+Abbiamo incontrato la problematica tipica che conduce all'uso dell'\textit{I/O
+ multiplexing} nella nostra analisi degli errori in
sez.~\ref{sec:TCP_conn_early_abort}, quando il nostro client non era in grado
di rendersi conto di errori sulla connessione essendo impegnato nella attesa
di dati in ingresso dallo \textit{standard input}.
diversi file descriptor, lo \textit{standard input}, da cui viene letto il
testo che vogliamo inviare al server, e il socket connesso con il server su
cui detto testo sarà scritto e dal quale poi si vorrà ricevere la
-risposta. L'uso dell'I/O multiplexing consente di tenere sotto controllo
+risposta. L'uso dell'\textit{I/O multiplexing} consente di tenere sotto controllo
entrambi, senza restare bloccati.
Nel nostro caso quello che ci interessa è non essere bloccati in lettura sullo
lettura (nell'ultimo caso anche in scrittura, ma questo non è necessario ai
nostri scopi).
-\begin{figure}[!htbp]
+\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{\codesamplewidth}
\includecodesample{listati/ClientEcho_third.c}
per il file descriptor associato al socket \var{socket} e per lo
\textit{standard input} (il cui valore si recupera con la funzione
\func{fileno}). Questo è necessario in quanto la successiva (\texttt{\small
- 13}) chiamata a \func{select} comporta una modifica dei due bit relativi,
-che quindi devono essere reimpostati all'inizio di ogni ciclo.
+ 13}) chiamata a \func{select} comporta una modifica dei due bit relativia
+questi file, che quindi devono essere reimpostati all'inizio di ogni ciclo.
Si noti come la chiamata a \func{select} venga eseguita usando come primo
argomento il valore di \var{maxfd}, precedentemente calcolato, e passando poi
il solo \textit{file descriptor set} per il controllo dell'attività in
-lettura, negli altri argomenti sono passati tutti puntatori nulli, non
-interessando né il controllo delle altre attività, né l'impostazione di un
-valore di timeout.
+lettura, negli altri argomenti vengono passati tutti puntatori nulli, non
+interessando in questo caso né il controllo delle altre attività, né
+l'impostazione di un valore di timeout.
Al ritorno di \func{select} si provvede a controllare quale dei due file
descriptor presenta attività in lettura, cominciando (\texttt{\small 14--24})
Controllato lo \textit{standard input} si passa a controllare (\texttt{\small
25--40}) il socket connesso, in caso di attività (\texttt{\small 26}) si
esegue subito una \func{read} di cui si controlla il valore di ritorno; se
-questo è negativo (\texttt{\small 27--30}) si è avuto un errore e pertanto si
-esce immediatamente segnalandolo, se è nullo (\texttt{\small 31--34})
-significa che il server ha chiuso la connessione, e di nuovo si esce con
-stampando prima un messaggio di avviso, altrimenti (\texttt{\small 35--39}) si
+questo è negativo si è avuto un errore e pertanto si esce immediatamente
+segnalandolo (\texttt{\small 27--30}), se è nullo significa che il server ha
+chiuso la connessione, e di nuovo si esce con stampando prima un messaggio di
+avviso (\texttt{\small 31--34}), altrimenti (\texttt{\small 35--39}) si
effettua la terminazione della stringa e la si stampa a sullo \textit{standard
- output} (uscendo in caso di errore), per ripetere il ciclo da capo.
+ output}, uscendo in caso di errore, per ripetere il ciclo da capo.
Con questo meccanismo il programma invece di essere bloccato in lettura sullo
\textit{standard input} resta bloccato sulla \func{select}, che ritorna
soltanto quando viene rilevata attività su uno dei due file descriptor posti
sotto controllo. Questo di norma avviene solo quando si è scritto qualcosa
sullo \textit{standard input}, o quando si riceve dal socket la risposta a quanto si
-era appena scritto. Ma adesso il client diventa capace di accorgersi
-immediatamente della terminazione del server; in tal caso infatti il server
-chiuderà il socket connesso, ed alla ricezione del FIN la funzione
-\func{select} ritornerà (come illustrato in sez.~\ref{sec:TCP_sock_select})
-segnalando una condizione di end of file, per cui il nostro client potrà
-uscire immediatamente.
+era appena scritto.
+
+Ma adesso il client diventa capace di accorgersi immediatamente della
+terminazione del server; in tal caso infatti il server chiuderà il socket
+connesso, ed alla ricezione del FIN la funzione \func{select} ritornerà (come
+illustrato in sez.~\ref{sec:TCP_sock_select}) segnalando una condizione di end
+of file, per cui il nostro client potrà uscire immediatamente.
Riprendiamo la situazione affrontata in sez.~\ref{sec:TCP_server_crash},
terminando il server durante una connessione, in questo caso quello che
in quanto il nostro client dopo aver inviato i dati non si bloccherà più nella
lettura dal socket, ma nella \func{select}; per questo potrà accettare
ulteriore dati che scriverà di nuovo sul socket, fintanto che c'è spazio sul
-buffer di uscita (ecceduto il quale si bloccherà in scrittura). Si ricordi
-infatti che il client non ha modo di determinare se la connessione è attiva o
-meno (dato che in molte situazioni reali l'inattività può essere temporanea).
-Tra l'altro se si ricollega la rete prima della scadenza del timeout, potremo
-anche verificare come tutto quello che si era scritto viene poi effettivamente
-trasmesso non appena la connessione ridiventa attiva, per cui otterremo
-qualcosa del tipo:
+buffer di uscita (ecceduto il quale si bloccherà in scrittura).
+
+Si ricordi infatti che il client non ha modo di determinare se la connessione
+è attiva o meno (dato che in molte situazioni reali l'inattività può essere
+temporanea). Tra l'altro se si ricollega la rete prima della scadenza del
+timeout, potremo anche verificare come tutto quello che si era scritto viene
+poi effettivamente trasmesso non appena la connessione ridiventa attiva, per
+cui otterremo qualcosa del tipo:
\begin{Console}
[piccardi@gont sources]$ \textbf{./echo 192.168.1.1}
Prima riga
caso di nuovo il client non è in grado di accorgersi di niente dato che si
suppone che il programma server non venga terminato correttamente, ma si
blocchi tutto senza la possibilità di avere l'emissione di un segmento FIN che
-segnala la terminazione della connessione. Di nuovo fintanto che la
-connessione non si riattiva (con il riavvio della macchina del server) il
-client non è in grado di fare altro che accettare dell'input e tentare di
-inviarlo. La differenza in questo caso è che non appena la connessione
-ridiventa attiva i dati verranno sì trasmessi, ma essendo state perse tutte le
-informazioni relative alle precedenti connessioni ai tentativi di scrittura
-del client sarà risposto con un segmento RST che provocherà il ritorno di
-\func{select} per la ricezione di un errore di \errcode{ECONNRESET}.
+segnala la terminazione della connessione.
+
+Di nuovo fintanto che la connessione non si riattiva (con il riavvio della
+macchina del server) il client non è in grado di fare altro che accettare
+dell'input e tentare di inviarlo. La differenza in questo caso è che non
+appena la connessione ridiventa attiva i dati verranno sì trasmessi, ma
+essendo state perse tutte le informazioni relative alle precedenti connessioni
+ai tentativi di scrittura del client sarà risposto con un segmento RST che
+provocherà il ritorno di \func{select} per la ricezione di un errore di
+\errcode{ECONNRESET}.
\subsection{La funzione \func{shutdown}}
\label{sec:TCP_shutdown}
-Come spiegato in sez.~\ref{sec:TCP_conn_term} il procedimento di chiusura di un
-socket TCP prevede che da entrambe le parti venga emesso un segmento FIN. È
+Come spiegato in sez.~\ref{sec:TCP_conn_term} il procedimento di chiusura di
+un socket TCP prevede che da entrambe le parti venga emesso un segmento FIN. È
pertanto del tutto normale dal punto di vista del protocollo che uno dei due
-capi chiuda la connessione, quando l'altro capo la lascia
-aperta.\footnote{abbiamo incontrato questa situazione nei vari scenari critici
- di sez.~\ref{sec:TCP_echo_critical}.}
+capi chiuda la connessione quando l'altro capo la lascia aperta; abbiamo
+incontrato questa situazione nei vari scenari critici di
+sez.~\ref{sec:TCP_echo_critical}.
\itindbeg{half-close}
-È pertanto possibile avere una situazione in cui un capo della connessione non
-avendo più nulla da scrivere, possa chiudere il socket, segnalando così
+È pertanto possibile avere una situazione in cui un capo della connessione,
+non avendo più nulla da scrivere, possa chiudere il socket, segnalando così
l'avvenuta terminazione della trasmissione (l'altro capo riceverà infatti un
\textit{end-of-file} in lettura) mentre dall'altra parte si potrà proseguire
la trasmissione dei dati scrivendo sul socket che da quel lato è ancora
aperto. Questa è quella situazione in cui si dice che il socket è
-``\textit{half closed}''.
+\textsl{mezzo chiuso} (``\textit{half closed}'').
Il problema che si pone è che se la chiusura del socket è effettuata con la
-funzione \func{close}, come spiegato in sez.~\ref{sec:TCP_func_close}, si perde
-ogni possibilità di poter rileggere quanto l'altro capo può continuare a
-scrivere. Per poter permettere allora di segnalare che si è concluso con la
+funzione \func{close}, come spiegato in sez.~\ref{sec:TCP_func_close}, si
+perde ogni possibilità di poter leggere quanto l'altro capo può star
+continuando a scrivere. Per permettere di segnalare che si è finito con la
scrittura, continuando al contempo a leggere quanto può provenire dall'altro
-capo del socket si può allora usare la funzione \funcd{shutdown}, il cui
-prototipo è:
-\begin{prototype}{sys/socket.h}
-{int shutdown(int sockfd, int how)}
+capo del socket, si può usare la funzione \funcd{shutdown}, il cui prototipo
+è:
-Chiude un lato della connessione fra due socket.
-
- \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
- errore, nel qual caso \var{errno} assumerà i valori:
+\begin{funcproto}{
+\fhead{sys/socket.h}
+\fdecl{int shutdown(int sockfd, int how)}
+\fdesc{Chiude un lato della connessione fra due socket.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{ENOTSOCK}] il file descriptor non corrisponde a un socket.
+ \item[\errcode{EBADF}] \param{sockfd} non è un file descriptor valido.
+ \item[\errcode{EINVAL}] il valore di \param{how} non è valido.
\item[\errcode{ENOTCONN}] il socket non è connesso.
- \end{errlist}
- ed inoltre \errval{EBADF}.}
-\end{prototype}
+ \item[\errcode{ENOTSOCK}] il file descriptor non corrisponde a un socket.
+ \end{errlist}}
+\end{funcproto}
La funzione prende come primo argomento il socket \param{sockfd} su cui si
vuole operare e come secondo argomento un valore intero \param{how} che indica
quando questa sembra rendere \func{shutdown} del tutto equivalente ad una
\func{close}. In realtà non è così, esiste infatti un'altra differenza con
\func{close}, più sottile. Finora infatti non ci siamo presi la briga di
-sottolineare in maniera esplicita che, come per i file e le fifo, anche per i
-socket possono esserci più riferimenti contemporanei ad uno stesso socket. Per
-cui si avrebbe potuto avere l'impressione che sia una corrispondenza univoca
-fra un socket ed il file descriptor con cui vi si accede. Questo non è
+sottolineare in maniera esplicita che, come per i file e le \textit{fifo},
+anche per i socket possono esserci più riferimenti contemporanei ad uno stesso
+socket.
+
+Per cui si avrebbe potuto avere l'impressione che sia una corrispondenza
+univoca fra un socket ed il file descriptor con cui vi si accede. Questo non è
assolutamente vero, (e lo abbiamo già visto nel codice del server di
fig.~\ref{fig:TCP_echo_server_first_code}), ed è invece assolutamente normale
che, come per gli altri oggetti, ci possano essere più file descriptor che
Fintanto che ci sono file descriptor che fanno riferimento ad un socket l'uso
di \func{close} si limiterà a deallocare nel processo corrente il file
descriptor utilizzato, ma il socket resterà pienamente accessibile attraverso
-tutti gli altri riferimenti. Se torniamo all'esempio originale del server di
+tutti gli altri riferimenti.
+
+Se torniamo all'esempio originale del server di
fig.~\ref{fig:TCP_echo_server_first_code} abbiamo infatti che ci sono due
\func{close}, una sul socket connesso nel padre, ed una sul socket in ascolto
nel figlio, ma queste non effettuano nessuna chiusura reale di detti socket,
del lato in scrittura, per segnalare all'altro capo della connessione che si è
concluso l'invio dei dati, restando comunque in grado di ricevere quanto
questi potrà ancora inviarci. Questo è ad esempio l'uso che ci serve per
-rendere finalmente completo il nostro esempio sul servizio \textit{echo}. Il
-nostro client infatti presenta ancora un problema, che nell'uso che finora ne
-abbiamo fatto non è emerso, ma che ci aspetta dietro l'angolo non appena
+rendere finalmente completo il nostro esempio sul servizio \textit{echo}.
+
+Il nostro client infatti presenta ancora un problema, che nell'uso che finora
+ne abbiamo fatto non è emerso, ma che ci aspetta dietro l'angolo non appena
usciamo dall'uso interattivo e proviamo ad eseguirlo redirigendo
\textit{standard input} e \textit{standard output}. Così se eseguiamo:
\begin{Console}
nostro client inizierà a leggere il contenuto del file \texttt{../fileadv.tex}
a blocchi di dimensione massima pari a \texttt{MAXLINE} per poi scriverlo,
alla massima velocità consentitagli dalla rete, sul socket. Dato che la
-connessione è con una macchina remota occorre un certo tempo perché i
+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
A questo punto, se torniamo al codice mostrato in
fig.~\ref{fig:TCP_ClientEcho_third}, possiamo vedere che mentre i pacchetti
sono in transito sulla rete il client continua a leggere e a scrivere fintanto
-che il file in ingresso finisce. Però non appena viene ricevuto un end-of-file
-in ingresso il nostro client termina. Nel caso interattivo, in cui si
-inviavano brevi stringhe una alla volta, c'era sempre il tempo di eseguire la
-lettura completa di quanto il server rimandava indietro. In questo caso
-invece, quando il client termina, essendo la comunicazione saturata e a piena
-velocità, ci saranno ancora pacchetti in transito sulla rete che devono
-arrivare al server e poi tornare indietro, ma siccome il client esce
-immediatamente dopo la fine del file in ingresso, questi non faranno a tempo a
-completare il percorso e verranno persi.
+che il file in ingresso finisce. Però non appena viene ricevuto un
+\textit{end-of-file} in ingresso il nostro client termina. Nel caso
+interattivo, in cui si inviavano brevi stringhe una alla volta, c'era sempre
+il tempo di eseguire la lettura completa di quanto il server rimandava
+indietro. In questo caso invece, quando il client termina, essendo la
+comunicazione saturata e a piena velocità, ci saranno ancora pacchetti in
+transito sulla rete che devono arrivare al server e poi tornare indietro, ma
+siccome il client esce immediatamente dopo la fine del file in ingresso,
+questi non faranno a tempo a completare il percorso e verranno persi.
Per evitare questo tipo di problema, invece di uscire una volta completata la
lettura del file in ingresso, occorre usare \func{shutdown} per effettuare la
del file in ingresso.
La seconda modifica (\texttt{\small 12--15}) è stata quella di rendere
-subordinato ad un valore nullo di \var{eof} l'impostazione del file descriptor
+subordinata ad un valore nullo di \var{eof} l'impostazione del file descriptor
set per l'osservazione dello \textit{standard input}. Se infatti il valore di
\var{eof} è non nullo significa che si è già raggiunta la fine del file in
ingresso ed è pertanto inutile continuare a tenere sotto controllo lo
funzione non esce dal ciclo principale (\texttt{\small 11--50}), ma continua
ad eseguirlo ripetendo la chiamata a \func{select} per tenere sotto controllo
soltanto il socket connesso, dal quale possono arrivare altri dati, che
-saranno letti (\texttt{\small 31}), ed opportunamente trascritti
+saranno letti (\texttt{\small 31}) ed opportunamente trascritti
(\texttt{\small 44--48}) sullo \textit{standard output}.
Il ritorno della funzione, e la conseguente terminazione normale del client,
viene invece adesso gestito all'interno (\texttt{\small 30--49}) della lettura
dei dati dal socket; se infatti dalla lettura del socket si riceve una
-condizione di end-of-file, la si tratterà (\texttt{\small 36--43}) in maniera
-diversa a seconda del valore di \var{eof}. Se infatti questa è diversa da zero
-(\texttt{\small 37--39}), essendo stata completata la lettura del file in
-ingresso, vorrà dire che anche il server ha concluso la trasmissione dei dati
-restanti, e si potrà uscire senza errori, altrimenti si stamperà
+condizione di \textit{end-of-file}, la si tratterà (\texttt{\small 36--43}) in
+maniera diversa a seconda del valore di \var{eof}. Se infatti questa è diversa
+da zero (\texttt{\small 37--39}), essendo stata completata la lettura del file
+in ingresso, vorrà dire che anche il server ha concluso la trasmissione dei
+dati restanti, e si potrà uscire senza errori, altrimenti si stamperà
(\texttt{\small 40--42}) un messaggio di errore per la chiusura precoce della
connessione.
-\subsection{Un server basato sull'I/O multiplexing}
+\subsection{Un server basato sull'\textit{I/O multiplexing}}
\label{sec:TCP_serv_select}
Seguendo di nuovo le orme di Stevens in \cite{UNP1} vediamo ora come con
-l'utilizzo dell'I/O multiplexing diventi possibile riscrivere completamente il
-nostro server \textit{echo} con una architettura completamente diversa, in
-modo da evitare di dover creare un nuovo processo tutte le volte che si ha una
-connessione.\footnote{ne faremo comunque una realizzazione diversa rispetto a
- quella presentata da Stevens in \cite{UNP1}.}
+l'utilizzo dell'\textit{I/O multiplexing} diventi possibile riscrivere
+completamente il nostro server \textit{echo} con una architettura
+completamente diversa, in modo da evitare di dover creare un nuovo processo
+tutte le volte che si ha una connessione.\footnote{ne faremo comunque una
+ realizzazione diversa rispetto a quella presentata da Stevens in
+ \cite{UNP1}.}
La struttura del nuovo server è illustrata in
fig.~\ref{fig:TCP_echo_multiplex}, in questo caso avremo un solo processo che
\begin{figure}[!htb]
\centering \includegraphics[width=13cm]{img/TCPechoMult}
- \caption{Schema del nuovo server echo basato sull'I/O multiplexing.}
+ \caption{Schema del nuovo server echo basato sull'\textit{I/O multiplexing}.}
\label{fig:TCP_echo_multiplex}
\end{figure}
In questo caso, una volta aperto e messo in ascolto il socket, tutto quello
che ci servirà sarà chiamare \func{select} per rilevare la presenza di nuove
connessioni o di dati in arrivo, e processarli immediatamente. Per realizzare
-lo schema mostrato in fig.~\ref{fig:TCP_echo_multiplex}, il programma usa una
+lo schema mostrato in fig.~\ref{fig:TCP_echo_multiplex} il programma usa una
tabella dei socket connessi mantenuta nel vettore \var{fd\_open} dimensionato
al valore di \const{FD\_SETSIZE}, ed una variabile \var{max\_fd} per
registrare il valore più alto dei file descriptor aperti.
tabella viene inizializzata (\texttt{\small 2}) a zero (valore che
utilizzeremo come indicazione del fatto che il relativo file descriptor non è
aperto), mentre il valore massimo (\texttt{\small 3}) per i file descriptor
-aperti viene impostato a quello del socket in ascolto,\footnote{in quanto esso
- è l'unico file aperto, oltre i tre standard, e pertanto avrà il valore più
- alto.} che verrà anche (\texttt{\small 4}) inserito nella tabella.
+aperti viene impostato a quello del socket in ascolto, in quanto esso è
+l'unico file aperto, oltre i tre standard, e pertanto avrà il valore più alto,
+che verrà anche (\texttt{\small 4}) inserito nella tabella.
La prima sezione (\texttt{\small 7--10}) del ciclo principale esegue la
costruzione del \textit{file descriptor set} \var{fset} in base ai socket
-connessi in un certo momento; all'inizio ci sarà soltanto il socket in
-ascolto, ma nel prosieguo delle operazioni, verranno utilizzati anche tutti i
-socket connessi registrati nella tabella \var{fd\_open}. Dato che la chiamata
-di \func{select} modifica il valore del \textit{file descriptor set}, è
-necessario ripetere (\texttt{\small 7}) ogni volta il suo azzeramento, per poi
-procedere con il ciclo (\texttt{\small 8--10}) in cui si impostano i socket
-trovati attivi.
+connessi in un certo momento; all'inizio ci sarà soltanto il socket in ascolto
+ma nel prosieguo delle operazioni verranno utilizzati anche tutti i socket
+connessi registrati nella tabella \var{fd\_open}. Dato che la chiamata di
+\func{select} modifica il valore del \textit{file descriptor set} è necessario
+ripetere (\texttt{\small 7}) ogni volta il suo azzeramento per poi procedere
+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_close}, per cui il kernel associa sempre ad ogni nuovo
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.
+ benché il kernel assegni sempre il primo valore libero, si potranno sempre
+ avere dei \textsl{buchi} nella nostra tabella dato che nelle operazioni i
+ socket saranno aperti e chiusi in corrispondenza della creazione e
+ conclusione delle connessioni.} 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
Se invece la funzione ritorna normalmente avremo in \var{n} il numero di
socket da controllare. Nello specifico si danno due possibili casi diversi per
cui \func{select} può essere ritornata: o si è ricevuta una nuova connessione
-ed è pronto il socket in ascolto, sul quale si può eseguire \func{accept} o
+ed è pronto il socket in ascolto, sul quale si può eseguire \func{accept}, o
c'è attività su uno dei socket connessi, sui quali si può eseguire
\func{read}.
Il primo caso viene trattato immediatamente (\texttt{\small 17--26}): si
controlla (\texttt{\small 17}) che il socket in ascolto sia fra quelli attivi,
nel qual caso anzitutto (\texttt{\small 18}) se ne decrementa il numero in
-\var{n}; poi, inizializzata (\texttt{\small 19}) la lunghezza della struttura
+\var{n}. Poi, inizializzata (\texttt{\small 19}) la lunghezza della struttura
degli indirizzi, si esegue \func{accept} per ottenere il nuovo socket connesso
controllando che non ci siano errori (\texttt{\small 20--23}). In questo caso
non c'è più la necessità di controllare per interruzioni dovute a segnali, in
aggiornare (\texttt{\small 25}) il valore massimo in \var{max\_fd}.
Una volta controllato l'arrivo di nuove connessioni si passa a verificare se
-vi sono dati sui socket connessi, per questo si ripete un ciclo
+ci sono dati sui socket connessi, per questo si ripete un ciclo
(\texttt{\small 29--55}) fintanto che il numero di socket attivi \var{n} resta
diverso da zero; in questo modo se l'unico socket con attività era quello
connesso, avendo opportunamente decrementato il contatore, il ciclo verrà
-saltato, e si ritornerà immediatamente (ripetuta l'inizializzazione del
-\textit{file descriptor set} con i nuovi valori nella tabella) alla chiamata
-di \func{accept}. Se il socket attivo non è quello in ascolto, o ce ne sono
-comunque anche altri, il valore di \var{n} non sarà nullo ed il controllo sarà
+saltato e si ritornerà immediatamente, ripetuta l'inizializzazione del
+\textit{file descriptor set} con i nuovi valori nella tabella, alla chiamata
+di \func{accept}.
+
+Se il socket attivo non è quello in ascolto, o ce ne sono comunque anche
+altri, il valore di \var{n} non sarà nullo ed il controllo sarà
eseguito. Prima di entrare nel ciclo comunque si inizializza (\texttt{\small
- 28}) il valore della variabile \var{i} che useremo come indice nella tabella
-\var{fd\_open} al valore minimo, corrispondente al file descriptor del socket
-in ascolto.
+ 28}) il valore della variabile \var{i}, che useremo come indice nella
+tabella, \var{fd\_open} al valore minimo, corrispondente al file descriptor
+del socket in ascolto.
Il primo passo (\texttt{\small 30}) nella verifica è incrementare il valore
dell'indice \var{i} per posizionarsi sul primo valore possibile per un file
messaggio in caso di errore (\texttt{\small 34--38}).
Se (\texttt{\small 39}) il numero di byte letti \var{nread} è nullo si è in
-presenza del caso di un \textit{end-of-file}, indice che una connessione che
-si è chiusa, che deve essere trattato (\texttt{\small 39--48}) opportunamente.
-Il primo passo è chiudere (\texttt{\small 40}) anche il proprio capo del
-socket e rimuovere (\texttt{\small 41}) il file descriptor dalla tabella di
-quelli aperti, inoltre occorre verificare (\texttt{\small 42}) se il file
-descriptor chiuso è quello con il valore più alto, nel qual caso occorre
-trovare (\texttt{\small 42--46}) il nuovo massimo, altrimenti (\texttt{\small
- 47}) si può ripetere il ciclo da capo per esaminare (se ne restano)
-ulteriori file descriptor attivi.
+presenza di un \textit{end-of-file}, indice che una connessione che si è
+chiusa, che deve essere trattato (\texttt{\small 39--48}) opportunamente. Il
+primo passo è chiudere (\texttt{\small 40}) anche il proprio capo del socket e
+rimuovere (\texttt{\small 41}) il file descriptor dalla tabella di quelli
+aperti, inoltre occorre verificare (\texttt{\small 42}) se il file descriptor
+chiuso è quello con il valore più alto, nel qual caso occorre trovare
+(\texttt{\small 42--46}) il nuovo massimo, altrimenti (\texttt{\small 47}) si
+può ripetere il ciclo da capo per esaminare (se ne restano) ulteriori file
+descriptor attivi.
Se però è stato chiuso il file descriptor più alto, dato che la scansione dei
file descriptor attivi viene fatta a partire dal valore più basso, questo
precedente versione (si riveda il codice di fig.~\ref{fig:TCP_ServEcho_second})
in cui si continuava a leggere fintanto che non si riceveva un
\textit{end-of-file}, questo perché usando l'\textit{I/O multiplexing} non si
-vuole essere bloccati in lettura. L'uso di \func{select} ci permette di
-trattare automaticamente anche il caso in cui la \func{read} non è stata in
-grado di leggere tutti i dati presenti sul socket, dato che alla iterazione
-successiva \func{select} ritornerà immediatamente segnalando l'ulteriore
-disponibilità.
+vuole essere bloccati in lettura.
+
+L'uso di \func{select} ci permette di trattare automaticamente anche il caso
+in cui la \func{read} non è stata in grado di leggere tutti i dati presenti
+sul socket, dato che alla iterazione successiva \func{select} ritornerà
+immediatamente segnalando l'ulteriore disponibilità.
Il nostro server comunque soffre di una vulnerabilità per un attacco di tipo
\textit{Denial of Service}. Il problema è che in caso di blocco di una
server si ferma e non risponde più a nessuna richiesta. Abbiamo scongiurato
questa evenienza per l'I/O in ingresso con l'uso di \func{select}, ma non vale
altrettanto per l'I/O in uscita. Il problema pertanto può sorgere qualora una
-delle chiamate a \func{write} effettuate da \func{FullWrite} si blocchi. Con
-il funzionamento normale questo non accade in quanto il server si limita a
+delle chiamate a \func{write} effettuate da \func{FullWrite} si blocchi.
+
+Con il funzionamento normale questo non accade in quanto il server si limita a
scrivere quanto riceve in ingresso, ma qualora venga utilizzato un client
malevolo che esegua solo scritture e non legga mai indietro l'\textsl{eco} del
server, si potrebbe giungere alla saturazione del buffer di scrittura, ed al
fine.
-
-\subsection{I/O multiplexing con \func{poll}}
+\subsection{\textit{I/O multiplexing} con \func{poll}}
\label{sec:TCP_serv_poll}
-Finora abbiamo trattato le problematiche risolubili con l'I/O multiplexing
-impiegando la funzione \func{select}; questo è quello che avviene nella
-maggior parte dei casi, in quanto essa è nata sotto BSD proprio per affrontare
-queste problematiche con i socket. Abbiamo però visto in
+Finora abbiamo trattato le problematiche risolubili con l'\textit{I/O
+ multiplexing} impiegando la funzione \func{select}. Questo è quello che
+avviene nella maggior parte dei casi, in quanto essa è nata sotto BSD proprio
+per affrontare queste problematiche con i socket. Abbiamo però visto in
sez.~\ref{sec:file_multiplexing} come la funzione \func{poll} possa costituire
-una alternativa a \func{select}, con alcuni vantaggi.\footnote{non soffrendo
- delle limitazioni dovute all'uso dei \textit{file descriptor set}.}
+una alternativa a \func{select}, con alcuni vantaggi, non soffrendo delle
+limitazioni dovute all'uso dei \textit{file descriptor set}.
Ancora una volta in sez.~\ref{sec:file_poll} abbiamo trattato la funzione in
maniera generica, parlando di file descriptor, ma come per \func{select}
-quando si ha a che fare con dei socket il concetto di essere \textsl{pronti}
-per l'I/O deve essere specificato nei dettagli, per tener conto delle
+quando si ha a che fare con dei socket, il concetto di essere \textsl{pronti}
+per l'I/O deve essere specificato nei dettagli per tener conto delle
condizioni della rete. Inoltre deve essere specificato come viene classificato
il traffico nella suddivisione fra dati normali e prioritari. In generale
pertanto:
di file descriptor attivi da controllare e ad eseguire (\texttt{\small 33}) la
lettura, ed in caso di errore (\texttt{\small 34--37}) al solito lo si
notificherà uscendo immediatamente. Qualora invece si ottenga una condizione
-di end-of-file (\texttt{\small 38--47}) si provvederà a chiudere
+di \textit{end-of-file} (\texttt{\small 38--47}) si provvederà a chiudere
(\texttt{\small 39}) anche il nostro capo del socket e a marcarlo
(\texttt{\small 40}) nella struttura ad esso associata come inutilizzato.
Infine dovrà essere ricalcolato (\texttt{\small 41--45}) un eventuale nuovo
Se invece si sono letti dei dati si provvede (\texttt{\small 48}) ad
effettuarne la riscrittura all'indietro, con il solito controllo ed eventuale
-uscita e notifica in caso si errore (\texttt{\small 49--52}).
+uscita e notifica in caso di errore (\texttt{\small 49--52}).
Come si può notare la logica del programma è identica a quella vista in
fig.~\ref{fig:TCP_SelectEchod} per l'analogo server basato su \func{select};
considerazioni finali di sez.~\ref{sec:TCP_serv_select}.
-
-\subsection{I/O multiplexing con \textit{epoll}}
+\subsection{\textit{I/O multiplexing} con \textit{epoll}}
\label{sec:TCP_serv_epoll}
Da fare.