\chapter{Un esempio completo di client/server TCP}
\label{cha:simple_TCP_sock}

In questo capitolo riprenderemo le funzioni trattate nel precedente, usandole
per scrivere una prima applicazione client/server che usi i socket TCP per una
comunicazione in entrambe le direzioni. 

Inoltre prenderemo in esame, oltre al comportamento in condizioni normali,
anche tutti i possibili scenari particolari (errori, sconnessione della rete,
crash del client o del server durante la connessione) che possono avere luogo
durante l'impiego di una applicazione di rete.


\section{Il servizio \texttt{echo}}
\label{sec:TCPsimp_echo}

L'applicazione scelta come esempio sarà una implementazione elementare, ma
completa, del servizio \texttt{echo}. Il servizio \texttt{echo} è uno dei
servizi standard solitamente provvisti direttamente dal superserver
\texttt{inetd}, ed è definito dall'RFC~862. Come dice il nome il servizio deve
rimandare indietro sulla connessione i dati che gli vengono inviati; l'RFC
descrive le specifiche sia per TCP che UDP, e per il primo stabilisce che una
volta stabilita la connessione ogni dato in ingresso deve essere rimandato in
uscita, fintanto che il chiamante non ha chiude la connessione; il servizio
opera sulla porta 7.

Nel nostro caso l'esempio sarà costituito da un client che legge una linea di
caratteri dallo standard input e la scrive sul server, il server leggerà la
linea dalla connessione e la riscriverà all'indietro; sarà compito del client
leggere la risposta del server e stamparla sullo standard output.

Si è scelto di usare questo servizio, seguendo lo Stevens, perché costituisce
il prototipo ideale di una generica applicazione di rete in cui un server
risponde alle richieste di un client; tutto quello che cambia nel caso si una
applicazione più complessa è la elaborazione dell'input del client da parte
del server nel fornire le risposte in uscita. 

\subsection{La struttura del server}
\label{sec:TCPsimp_server_main}

Il server si compone di un corpo principale, costituito dalla funzione
\texttt{main} che si incarica di creare il socket, metterlo in ascolto di
connessioni in arrivo e creare un processo figlio a cui delegare la gestione
di ciascuna connessione. Questa parte, riportata in \nfig, è sostanzialmente
identica a quella vista nell'esempio in \figref{sec:TCPelem_serv_code}.

\begin{figure}[!htb]
  \footnotesize
  \begin{lstlisting}{}
/* Subroutines declaration */
void SockEcho(int sockfd);
/* Program beginning */
int main(int argc, char *argv[])
{
    int list_fd, conn_fd;
    pid_t pid;
    struct sockaddr_in serv_add;
     ....
    /* create socket */
    if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket creation error");
        exit(-1);
    }
    /* initialize address */
    memset((void *)&serv_add, 0, sizeof(serv_add)); /* clear server address */
    serv_add.sin_family = AF_INET;                  /* address type is INET */
    serv_add.sin_port = htons(13);                  /* daytime port is 13 */
    serv_add.sin_addr.s_addr = htonl(INADDR_ANY);   /* connect from anywhere */
    /* bind socket */
    if (bind(list_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) {
        perror("bind error");
        exit(-1);
    }
    /* listen on socket */
    if (listen(list_fd, BACKLOG) < 0 ) {
        perror("listen error");
        exit(-1);
    }
    /* handle echo to client */
    while (1) {
        /* accept connection */
        if ( (conn_fd = accept(list_fd, NULL, NULL)) < 0) {
            perror("accept error");
            exit(-1);
        }
        /* fork to handle connection */
        if ( (pid = fork()) < 0 ){
            perror("fork error");
            exit(-1);
        }
        if (pid == 0) {      /* child */
            close(list_fd);          /* close listening socket */   
            SockEcho(conn_fd);       /* handle echo */
            exit(0);
        } else {             /* parent */
            close(conn_fd);          /* close connected socket */
        }
    }
    /* normal exit, never reached */
    exit(0);
}
  \end{lstlisting}
  \caption{Codice della funzione \texttt{main} del server
    \texttt{SimpleEchoTCPServer.c} per il servizio \texttt{echo}.}
  \label{fig:TCPsimpl_serv_code}
\end{figure}

La struttura del server è sostanzialmente a quella dell'esempio precedente, ed
ad esso si applicano le considerazioni fatte in
\secref{sec:TCPel_cunc_daytime}, le uniche differenze rispetto all'esempio in
\figref{sec:TCPelem_serv_code} è che in questo caso per il socket in ascolto
viene usata la porta 7 e tutta la gestione della comunicazione è delegata alla
funzione \texttt{SockEcho}.



\subsection{Il client}
\label{sec:TCPsimp_server_main}


