 %% tcpsockadv.tex
%%
%% Copyright (C) 2003 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 "Prefazione",
%% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
%% license is included in the section entitled "GNU Free Documentation
%% License".
%%
\chapter{Socket TCP avanzati}
\label{cha:TCP_advanced}

Esamineremo in questo capitolo le funzionalità più evolute della gestione dei
socket TCP. 



\section{Socket multiplexing}
\label{sec:TCP_sock_multiplexing}

Affronteremo in questa sezione l'utilizzo dell'I/O multiplexing, affrontato in
\secref{sec:file_multiplexing}, nell'ambito delle applicazioni di rete. Già in
\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.

Abbiamo visto in \secref{sec:file_multiplexing} quali sono le funzionalità del
sistema che ci permettono di tenere sotto controllo più file descriptor in
contemporanea; in quella occasione non abbiamo fatto esempi, in quanto quando
si tratta con file normali questa tipologia di I/O non viene usata, è invece
un caso tipico delle applicazioni di rete quello di dover gestire varie
connessioni da cui possono arrivare dati comuni in maniera asincrona, per cui
riprenderemo l'argomento in questa sezione.



\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 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 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.}




\section{Le opzioni dei socket}
\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, abbiamo
preferito trattare l'argomento in generale in questa sezione piuttosto che
nel capitolo dedicato alla trattazione generica dei socket.



\section{I dati \textit{out-of-band}}
\label{sec:TCP_outofband}

Una caratteristica speciale dei socket TCP è quella della presenza dei
cosiddetti dati \textit{out-of-band}



\subsection{La funzione \func{shutdown}}
\label{sec:TCP_shutdown}

Come spiegato in \secref{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 \secref{sec:TCP_echo_critical}.}

È 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
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}.

Il problema che si pone è che se la chiusura del socket è effettuata con la
funzione \func{close}, come spiegato in \secref{sec:TCP_func_close}, si perde
ogni possibilità di poter rileggere quanto l'altro capo può continuare a
scrivere. Per poter permettere allora 




%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "gapil"
%%% End: 
