order}) e viceversa; in questo caso si usa la lettera $a$ come mnemonico per
indicare la stringa. Dette funzioni sono:
\begin{itemize}
-\item \texttt{int inet\_aton(const char *strptr, struct in\_addr *addrptr)}
+\item \texttt{int inet\_aton(const char *src, struct in\_addr *dest)}
- Converte la stringa puntata da \texttt{strptr} nell'indirizzo binario da
- memorizzare all'indirizzo puntato da \texttt{addrptr}, restituendo 0 in caso
+ Converte la stringa puntata da \texttt{src} nell'indirizzo binario da
+ memorizzare all'indirizzo puntato da \texttt{dest}, restituendo 0 in caso
di successo e 1 in caso di fallimento (è espressa in questa forma in modo da
poterla usare direttamente con il puntatore usato per passare la struttura
- degli indirizzi). Se usata con \texttt{addrptr} inizializzato a
+ degli indirizzi). Se usata con \texttt{dest} inizializzato a
\texttt{NULL} effettua la validazione dell'indirizzo.
\item \texttt{in\_addr\_t inet\_addr(const char *strptr)}
\texttt{INET6\_ADDRSTRLEN} per indirizzi IPv6; la lunghezza del buffer deve
comunque venire specificata attraverso il parametro \texttt{len}.
- La funzione restitisce un puntatore non nullo a \texttt{dest} in caso di
+ La funzione restituisce un puntatore non nullo a \texttt{dest} in caso di
successo e un puntatore nullo in caso di fallimento, in quest'ultimo caso
viene settata la variabile \texttt{errno} con il valore \texttt{ENOSPC} in
caso le dimensioni dell'indirizzo eccedano la lunghezza specificata da
\label{sec:sock_io_behav}
Una cosa di cui non sempre si è consapevoli quando si ha a che fare con i
-socket è che le funzioni di I/O non sempre hanno lo stesso comportamento che
-avrebbero con i normali files (in particolare questo è vero nel caso si stream
-socket). Infatti con i socket funzioni come \texttt{read} o \texttt{write}
-possono restituire in input o scrivere in output un numero di bytes minore di
-quello richiesto, e questo è un comportamento normale e non un errore. Ciò
-avviene perché il kernel può
+socket è che le funzioni di input/output non sempre hanno lo stesso
+comportamento che avrebbero con i normali files (in particolare questo accade
+per i socket di tipo stream).
+
+Infatti con i socket può accadere che funzioni come \texttt{read} o
+\texttt{write} possano restituire in input o scrivere in output un numero di
+bytes minore di quello richiesto. Questo è un comportamento normale e non un
+errore, e succede perché si eccede il limite di buffer del kernel. In questo
+caso tutto quello che il programma chiamante deve fare è di ripetere la
+lettura (o scrittura) per la quantità di bytes rimanenti (lo stesso può
+avvenire scrivendo più di 4096 bytes in una pipe, dato che quello è il limite
+di solito adottato per il buffer di trasmissione del kernel).
+
+\begin{figure}[htb]
+ \centering
+ \footnotesize
+ \begin{lstlisting}{}
+#include <unistd.h>
+
+ssize_t SockRead(int fd, void *buf, size_t count)
+{
+ size_t nleft;
+ ssize_t nread;
+
+ nleft = count;
+ while (nleft > 0) { /* repeat until no left */
+ if ( (nread = read(fd, buf, nleft)) < 0) {
+ if (errno == EINTR) { /* if interrupted by system call */
+ continue; /* repeat the loop */
+ } else {
+ return(nread); /* otherwise exit */
+ }
+ } else if (nread == 0) { /* EOF */
+ break; /* break loop here */
+ }
+ nleft -= nread; /* set left to read */
+ buf +=nread; /* set pointer */
+ }
+ return (count - nleft);
+}
+ \end{lstlisting}
+ \caption{Funzione \texttt{SockRead}, legge $n$ bytes da un socket }
+ \label{fig:sock_SockRead_code}
+\end{figure}
+Per questo motivo seguendo l'esempio di W. R. Stevens si sono definite due
+funzioni \texttt{SockRead} e \texttt{SockWrite} che eseguono la lettura da un
+socket tenendo conto di questa caratteristica, ed in grado di ritornare dopo
+avere letto o scritto esattamente il numero di bytes specificato; il sorgente
+è riportato in \curfig\ e \nfig\ ed è disponibile fra i sorgenti allegati alla
+guida nei files \texttt{SockRead.c} e \texttt{SockWrite.c}.
+\begin{figure}[htb]
+ \centering
+ \footnotesize
+ \begin{lstlisting}{}
+#include <unistd.h>
+
+ssize_t SockWrite(int fd, const void *buf, size_t count)
+{
+ size_t nleft;
+ ssize_t nwritten;
+
+ nleft = count;
+ while (nleft > 0) { /* repeat until no left */
+ if ( (nwritten = write(fd, buf, nleft)) < 0) {
+ if (errno == EINTR) { /* if interrupted by system call */
+ continue; /* repeat the loop */
+ } else {
+ return(nwritten); /* otherwise exit with error */
+ }
+ }
+ nleft -= nwritten; /* set left to write */
+ buf +=nwritten; /* set pointer */
+ }
+ return (count);
+}
+ \end{lstlisting}
+ \caption{Funzione \texttt{SockWrite}, scrive $n$ bytes su un socket }
+ \label{fig:sock_SockWrite_code}
+\end{figure}
+Come si può notare le funzioni ripetono la lettura/scrittura in un loop fino
+all'esaurimento del numero di bytes richiesti, in caso di errore viene
+controllato se questo è \texttt{EINTR} (cioè un'interruzione della system call
+dovuta ad un segnale), nel qual caso l'accesso viene ripetuto, altrimenti
+l'errore viene ritornato interrompendo il loop.
+Nel caso della lettura se il numero di bytes letti è zero significa che è
+arrivati alla fine del file e pertanto si ritorna senza aver concluso la
+lettura di tutti i bytes richiesti.
\chapter{Socket TCP elementari}
\label{cha:elem_TCP_sock}
-Esamineremo in questo capitolo quanto necessario per capire come scrivere un
-client e un server TCP, riprendendo quanto visto in \ref{sec:net_cli_sample} e
-\ref{sec:net_cli_server}.
+In questo capitolo esamineremo i vari dettagli necessari per capire il
+funzionamento dei socket TCP, partendo dai due esempi elementari visti in
+precedenza (vedi \ref{sec:net_cli_sample} e \ref{sec:net_cli_server}), per
+arrivare a scrivere una semplice applicazione client/server completa
+(l'implementazione del servizio \texttt{time} su TCP).
+Tratteremo qui dunque il funzionamento delle varie funzioni che si sono usate
+nell'esempio precedente e daremo una descrizione delle principali
+caratteristiche del funzionamento di una connessione TCP.
-\subsection{Creazione e terminazione della connessione TCP}
+\section{Il funzionamento di una connessione TCP}
+\label{sec:TCPel_connession}
+
+Prima di entrare nei dettagli del funzionamento delle funzioni della
+interfaccia dei socket che operano con TCP (\texttt{connect}, \texttt{accept},
+\texttt{close}) è fondamentale capire alcune basi del funzionamento di una
+connessione TCP, in particolare su come la si stabilisce e come la si
+conclude e sul diagramma degli stati del TCP.
+
+\subsection{Creazione: il \textit{three way handshake}}
+\label{sec:TCPel_conn_cre}
+
+\subsection{Il significato delle opzioni del TCP}
+\label{sec:TCPel_TCP_opt}
+
+\subsection{La terminazione della connessione}
+\label{sec:TCPel_conn_term}
+
+\subsection{Il diagramma delle transizioni di stato}
+\label{sec:TCPel_trans_dia}
+
+\subsection{Lo stato \texttt{TIME\_WAIT}}
+\label{sec:TCPel_time_wait}
+
+
+\section{I numeri di porta}
+\label{sec:TCPel_ports}
+
+\section{Le funzioni dei socket TCP}
+\label{sec:TCPel_functions}
+
+\subsection{La funzione \texttt{connect}}
+\label{sec:TCPel_func_connect}
+
+\subsection{La funzione \texttt{bind}}
+\label{sec:TCPel_func_bind}
+
+\subsection{La funzione \texttt{listen}}
+\label{sec:TCPel_func_listen}
+
+\subsection{La funzione \texttt{connect}}
+\label{sec:TCPel_func_connect}
+
+\subsection{La funzione \texttt{accept}}
+\label{sec:TCPel_func_accept}
-Per capire il funzionamento delle funzioni della interfaccia dei socket che
-operano con TCP (le varie \texttt{connect}, \texttt{accept}, \texttt{close}
-che abbiamo visto negli esempi iniziali e su cui torneremo più avanti) è
-fodamentale capire come funziona la creazione e la conclusione di una
-connessione TCP.
\subsection{Le porte}
+