\label{cha:elem_TCP_sock}
In questo capitolo iniziamo ad approfondire la conoscenza dei socket TCP,
-tratteremo qui dunque il funzionamento delle varie funzioni che si sono usate
-nei due esempi elementari forniti in precedenza (vedi
-\secref{sec:net_cli_sample} e \secref{sec:net_serv_sample}), previa una
-descrizione delle principali caratteristiche del funzionamento di una
-connessione TCP.
+tratteremo qui dunque le varie funzioni che si sono usate nei due esempi
+elementari forniti nel capitolo precedente (vedi \secref{sec:net_cli_sample} e
+\secref{sec:net_serv_sample}), previa una descrizione delle principali
+caratteristiche del funzionamento di una connessione TCP.
\section{Il funzionamento di una connessione TCP}
Prima di entrare nei dettagli delle funzioni usate nelle applicazioni che
utilizzano i socket TCP, è fondamentale spiegare alcune basi del funzionamento
del TCP; la conoscenza del funzionamento del protocollo è infatti essenziale
-per capire il modello di programmazione ed il funzionamento delle API.
+per capire il modello di programmazione ed il funzionamento delle interfacce
+di programmazione.
In particolare ci concentreremo sulle modalità con le quali il protocollo dà
inizio e conclude una connessione; faremo inoltre anche un breve accenno al
\const{INADDR\_ANY}, il cui valore, come visto anche negli esempi precedenti
è pari a zero, nell'esempio \figref{fig:net_serv_code} si è usata
un'assegnazione immediata del tipo:
-
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */
-\end{lstlisting}
+\includecodesnip{listati/serv_addr_sin_addr.c}
Si noti che si è usato \func{htonl} per assegnare il valore
\const{INADDR\_ANY}, benché essendo questo pari a zero il riordinamento sia
\const{in6addr\_any} (dichiarata come \direct{extern}, ed inizializzata dal
sistema al valore \const{IN6ADRR\_ANY\_INIT}) che permette di effettuare una
assegnazione del tipo:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-serv_add.sin6_addr = in6addr_any; /* connect from anywhere */
-\end{lstlisting}
+\includecodesnip{listati/serv_addr_sin6_addr.c}
in maniera analoga si può utilizzare la variabile \const{in6addr\_loopback}
per indicare l'indirizzo di \textit{loopback}, che a sua volta viene
inizializzata staticamente a \const{IN6ADRR\_LOOPBACK\_INIT}.
\file{ElemDaytimeTCPCuncServ.c} è allegato nella directory dei sorgenti.
\begin{figure}[!htb]
- \footnotesize
- \begin{lstlisting}{}
-#include <sys/types.h> /* predefined types */
-#include <unistd.h> /* include unix standard library */
-#include <arpa/inet.h> /* IP addresses conversion utililites */
-#include <sys/socket.h> /* socket library */
-#include <stdio.h> /* include standard I/O library */
-#include <time.h>
-
-int main(int argc, char *argv[])
-{
- int list_fd, conn_fd;
- int i;
- struct sockaddr_in serv_add, client;
- char buffer[MAXLINE];
- socklen_t len;
- time_t timeval;
- pid_t pid;
- int logging=0;
- ...
- /* write daytime to client */
- while (1) {
- if ( (conn_fd = accept(list_fd, (struct sockaddr *)&client, &len))
- <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);
- timeval = time(NULL);
- snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&timeval));
- if ( (write(conn_fd, buffer, strlen(buffer))) < 0 ) {
- perror("write error");
- exit(-1);
- }
- if (logging) {
- inet_ntop(AF_INET, &client.sin_addr, buffer, sizeof(buffer));
- printf("Request from host %s, port %d\n", buffer,
- ntohs(client.sin_port));
- }
- close(conn_fd);
- exit(0);
- } else { /* parent */
- close(conn_fd);
- }
- }
- /* normal exit, never reached */
- exit(0);
-}
- \end{lstlisting}
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/ElemDaytimeTCPCuncServ.c}
+ \end{minipage}
+ \normalsize
\caption{Esempio di codice di un server concorrente elementare per il
servizio daytime.}
\label{fig:TCPel_serv_code}