Completata sezione sulla risoluzione di nomi ed indirizzi, iniziato a
authorSimone Piccardi <piccardi@gnulinux.it>
Wed, 8 Dec 2004 14:49:24 +0000 (14:49 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Wed, 8 Dec 2004 14:49:24 +0000 (14:49 +0000)
strutturare il prosieguo del lavoro.

listati/TCP_echod_third.c
sockadv.tex
sockctrl.tex
sources/TCP_echod.c
sources/TCP_echod_third.c

index c150ad4..a9149ae 100644 (file)
@@ -13,7 +13,6 @@ int main(int argc, char *argv[])
     }
     /* create and bind socket */
     if ( (list_fd = sockbind(argv[optind], "echo", 6, SOCK_STREAM)) < 0) {
-       if (errno) perror("Socket creation error");
        return 1;
     }   
     ...
index b5d58db..9297e1c 100644 (file)
@@ -18,12 +18,12 @@ e la gestione dei dati urgenti e \textit{out-of-band}.
 
 
 
-\section{Socket TCP avanzati}
-\label{sec:TCP_advanced_socket}
-
-Trattereno in questa sezione alcune delle funzionalità più avanzate relative
-ai socket TCP. Da fare
+\section{Le funzioni di I/O avanzate}
+\label{sec:sock_advanced_IO}
 
+Trattereno in questa sezione le funzioni di I/O più avanzate che permettono di
+controllare le funzionalità specifiche della comunicazione dei dati che sono
+disponibili con i vari tipi di socket.
 
 
 \subsection{I dati \textit{out-of-band}}
@@ -33,11 +33,13 @@ Una caratteristica speciale dei socket TCP 
 cosiddetti dati \textit{out-of-band} ...
 
 
-\section{Socket UDP avanzati}
-\label{sec:UDP_advanced_socket}
+\section{L'uso dell'I/O non bloccante}
+\label{sec:sock_noblok_IO}
+
+Trattereno in questa sezione le modalità avanzate che permettono di utilizzare
+i socket con una comunicazione non bloccante, in modo da 
+
 
-Trattereno in questa sezione alcune delle funzionalità più avanzate relative
-ai socket UDP. Da fare
 
 
 
index 594e608..a67e9b6 100644 (file)
@@ -1688,17 +1688,14 @@ indicano il nome della macchina a cui collegarsi ed il relativo servizio su
 cui sarà effettuata la risoluzione; seguono il protocollo da usare (da
 specificare con il valore numerico di \file{/etc/protocols}) ed il tipo di
 socket (al solito specificato con i valori illustrati in
-sez.~\ref{sec:sock_type}).
-
-La funzione ritorna il valore del file descriptor (un numero positivo)
-associato al socket in caso di successo, o -1 in caso di errore. Per risolvere
-il problema di non poter passare indietro i valori di ritorno di
-\func{getaddrinfo} con i codici di errore\footnote{non si può avere nessuna
-  certezza che detti valori siano negativi, è questo è invece nessario per
-  evitare ogni possibile ambiguità nei confronti del valore di ritorno in caso
-  di successo.} si è provvisto a stampare direttamente all'interno della
-funzione i rispettivi errori, si potrà riconoscere questo caso ottenendo -1
-per il valore di ritorno, ma un valore nullo di \var{errno}.
+sez.~\ref{sec:sock_type}).  La funzione ritorna il valore del file descriptor
+associato al socket (un numero positivo) in caso di successo, o -1 in caso di
+errore; per risolvere il problema di non poter passare indietro i valori di
+ritorno di \func{getaddrinfo} contenenti i relativi codici di
+errore\footnote{non si può avere nessuna certezza che detti valori siano
+  negativi, è questo è invece nessario per evitare ogni possibile ambiguità
+  nei confronti del valore di ritorno in caso di successo.} si sono stampati i
+messaggi d'errore direttamente nella funzione.
 
 Una volta definite le variabili necessarie (\texttt{\small 3--5}) la funzione
 prima (\texttt{\small 6}) azzera il contenuto della struttura \var{hint} e poi
@@ -1707,40 +1704,46 @@ chiamata (\texttt{\small 10}) a \func{getaddrinfo}. Di quest'ultima si
 controlla (\texttt{\small 12-16}) il codice di ritorno, in modo da stampare un
 avviso di errore, azzerare \var{errno} ed uscire in caso di errore.  Dato che
 ad una macchina possono corrispondere più indirizzi IP, e di tipo diverso (sia
-IPv4 che IPv6), ed il servizio può essere in ascolto soltanto su uno solo di
-questi, si provvede a tentare la connessione per ciascun indirizzo restituito
-all'interno di un ciclo (\texttt{\small 18-40}) di scansione della lista
-restituita da \func{getaddrinfo}, ma prima (\texttt{\small 17}) si salva il
-valore del puntatore per poterlo riutilizzare alla fine per disallocare la
+IPv4 che IPv6), mantre il servizio può essere in ascolto soltanto su uno solo
+di questi, si provvede a tentare la connessione per ciascun indirizzo
+restituito all'interno di un ciclo (\texttt{\small 18-40}) di scansione della
+lista restituita da \func{getaddrinfo}, ma prima (\texttt{\small 17}) si salva
+il valore del puntatore per poterlo riutilizzare alla fine per disallocare la
 lista.
 
-Il ciclo viene ripetuto fintanto che si hanno indirizzi validi, ed inizia
-(\texttt{\small 19}) con l'apertura del socket; se questa fallisce si
-controlla (\texttt{\small 20}) se sono disponibili altri indirizzi, nel qual
-caso si passa al successivo (\texttt{\small 21}) ricominciando il ciclo
-(\texttt{\small 22}), se non ve ne sono si stampa l'errore ritornado
-immediatamente (\texttt{\small 24-27}). Se la creazione del socket ha avuto
-successo si procede (\texttt{\small 29}) con la connessione
-
-
-
-
-
-Se la risoluzione del nome ha successo si provvede (\texttt{\small 19--23}) ad
-aprire il socket, ed a connettersi ad esso (\texttt{\small 25--29}); in
-entrambi casi si gestisce il caso di errore, con una stampa ed il ritorno del
-valore -1. Infine prima di ritornare (\texttt{\small 31}) il valore del file
-descriptor del socket si provvede (\texttt{\small 30}) a liberare le strutture
-\struct{addrinfo} allocate da \func{getaddrinfo}.
-
-Si noti come la funzione si limiti ad usare i valori contenuti nella prima
-struttura \struct{addrinfo} ritornata da \func{getaddrinfo}, non eseguendo
-ulteriori tentativi sulle successive in caso di errore. Un'altra
-caratteristica della funzione è che è del tutto irrilevante se la struttura
-ritornata usa indirizzi IPv6 o IPv4, in quanto si fa uso direttamente dei dati
-relativi alle strutture degli indirizzi di \struct{addrinfo} che sono
+Il ciclo viene ripetuto (\texttt{\small 18}) fintanto che si hanno indirizzi
+validi, ed inizia (\texttt{\small 19}) con l'apertura del socket; se questa
+fallisce si controlla (\texttt{\small 20}) se sono disponibili altri
+indirizzi, nel qual caso si passa al successivo (\texttt{\small 21}) e si
+riprende (\texttt{\small 22}) il ciclo da capo; se non ve ne sono si stampa
+l'errore ritornando immediatamente (\texttt{\small 24-27}). Quando la
+creazione del socket ha avuto successo si procede (\texttt{\small 29})
+direttamente con la connessione, di nuovo in caso di fallimento viene ripetuto
+(\texttt{\small 30--38}) il controllo se vi sono o no altri indirizzi da
+provare nella stessa modalità fatta in precedenza, aggiungendovi però in
+entrambi i casi (\texttt{\small 32} e (\texttt{\small 36}) la chiusura del
+socket precedentemente aperto, che non è più utilizzabile.
+
+Se la connessione ha avuto successo invece si termina (\texttt{\small 39})
+direttamente il ciclo, e prima di ritornare (\texttt{\small 31}) il valore del
+file descriptor del socket si provvede (\texttt{\small 30}) a liberare le
+strutture \struct{addrinfo} allocate da \func{getaddrinfo} utilizzando il
+valore del relativo puntatore precedentemente (\texttt{\small 17}) salvato.
+Si noti come per la funzione sia del tutto irrilevante se la struttura
+ritornata contiene indirizzi IPv6 o IPv4, in quanto si fa uso direttamente dei
+dati relativi alle strutture degli indirizzi di \struct{addrinfo} che sono
 \textsl{opachi} rispetto all'uso della funzione \func{connect}.
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/TCP_echo_fifth.c}
+  \end{minipage}
+  \normalsize
+  \caption{Il nuovo codice per la connessione del client \textit{echo}.}
+  \label{fig:TCP_echo_fifth}
+\end{figure}
+
 Per usare questa funzione possiamo allora modificare ulteriormente il nostro
 programma client per il servizio \textit{echo}; in questo caso rispetto al
 codice usato finora per collegarsi (vedi fig.~\ref{fig:TCP_echo_client_1})
@@ -1755,11 +1758,11 @@ dell'indirizzo numerico, e pu
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \includecodesample{listati/TCP_echo_fifth.c}
+    \includecodesample{listati/sockbind.c}
   \end{minipage}
   \normalsize
-  \caption{Il nuovo codice per la connessione del client \textit{echo}.}
-  \label{fig:TCP_echo_fifth}
+  \caption{Il codice della funzione \func{sockbind}.}
+  \label{fig:sockbind_code}
 \end{figure}
 
 La seconda funzione di ausilio è \func{sockbind}, il cui corpo principale è
@@ -1768,55 +1771,37 @@ nel file \file{sockbind.c} dei sorgenti allegati alla guida). Come si pu
 notare la funzione è del tutto analoga alla precedente \func{sockconn}, e
 prende gli stessi argomenti, però invece di eseguire una connessione con
 \func{connect} si limita a chiamare \func{bind} per collegare il socket ad una
-porta. 
+porta.
 
-Dato che la funzione è pensata per utilizzata da un server ci si può chiedere
-a quale scopo mantenere l'argomento \param{host} quando l'indirizzo di questo
-è usualmente noto. Si ricordi però quanto detto in
+Dato che la funzione è pensata per essere utilizzata da un server ci si può
+chiedere a quale scopo mantenere l'argomento \param{host} quando l'indirizzo
+di questo è usualmente noto. Si ricordi però quanto detto in
 sez.~\ref{sec:TCP_func_bind}, relativamente al significato della scelta di un
 indirizzo specifico come argomento di \func{bind}, che consente di porre il
 server in ascolto su uno solo dei possibili diversi indirizzi presenti su di
-una macchina. 
-
-Se non si vuole che la funzione esegua \func{bind} su un indirizzo specifico,
-ma utilizzi l'indirizzo generico, occorrerà avere cura di passare un valore
-\const{NULL} come valore per l'argomento \var{host}; l'uso del valore
-\const{AI\_PASSIVE} serve ad ottenere il valore generico nella rispettiva
-struttura degli indirizzi.
-
-\begin{figure}[!htb]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \includecodesample{listati/sockbind.c}
-  \end{minipage}
-  \normalsize
-  \caption{Il codice della funzione \func{sockbind}.}
-  \label{fig:sockbind_code}
-\end{figure}
+una macchina.  Se non si vuole che la funzione esegua \func{bind} su un
+indirizzo specifico, ma utilizzi l'indirizzo generico, occorrerà avere cura di
+passare un valore \const{NULL} come valore per l'argomento \var{host}; l'uso
+del valore \const{AI\_PASSIVE} serve ad ottenere il valore generico nella
+rispettiva struttura degli indirizzi.
 
 Come già detto la funzione è analoga a \func{sockconn} ed inizia azzerando ed
 inizializzando (\texttt{\small 6-11}) opportunamente la struttura \var{hint}
 con i valori ricevuti come argomenti, soltanto che in questo caso si è usata
 (\texttt{\small 8}) una impostazione specifica dei flag di \var{hint} usando
 \const{AI\_PASSIVE} per indicare che il socket sarà usato per una apertura
-passiva. Per il resto la chiamata a \func{getaddrinfo} (\texttt{\small 12-17})
-e quella a \func{socket} (\texttt{\small 19--23}) sono identiche, mentre si è
-sostituita (\texttt{\small 25--29}) la chiamata a \func{connect} con una
-chiamata a \func{bind}. La conclusione (\texttt{\small 30--31}) della funzione
-è identica. Si noti come anche in questo caso si siano inserite le stampe
-degli errori sullo standard output, nonostante la funzione possa essere
-invocata da un demone. Nel nostro caso questo non è un problema in quanto se
-la funzione non ha successo il programma deve uscire immediatamente prima di
-essere posto in background, e può quindi scrivere gli errori direttamente
-sullo standard output.
-
-Con l'uso di questa funzione si può modificare anche il codice del nostro
-server \textit{echo}, che rispetto a quanto illustrato nella versione iniziale
-di fig.~\ref{fig:TCP_echo_server_first_code} viene modificato nella forma
-riportata in fig.~\ref{fig:TCP_echod_third}. In questo caso il socket su cui
-porsi in ascolto viene ottenuto (\texttt{\small 15--18}) da \func{sockbind}
-che si cura anche della eventuale risoluzione di un indirizzo specifico sul
-quale si voglia far ascoltare il server.
+passiva. Per il resto la chiamata (\texttt{\small 12-18}) a \func{getaddrinfo}
+e ed il ciclo principale (\texttt{\small 20--42}) sono identici, solo che si è
+sostituita (\texttt{\small 31}) la chiamata a \func{connect} con una chiamata
+a \func{bind}. Anche la conclusione (\texttt{\small 43--44}) della funzione è
+identica. 
+
+Si noti come anche in questo caso si siano inserite le stampe degli errori
+sullo standard error, nonostante la funzione possa essere invocata da un
+demone. Nel nostro caso questo non è un problema in quanto se la funzione non
+ha successo il programma deve uscire immediatamente prima di essere posto in
+background, e può quindi scrivere gli errori direttamente sullo standard
+error.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1828,23 +1813,73 @@ quale si voglia far ascoltare il server.
   \label{fig:TCP_echod_third}
 \end{figure}
 
+Con l'uso di questa funzione si può modificare anche il codice del nostro
+server \textit{echo}, che rispetto a quanto illustrato nella versione iniziale
+di fig.~\ref{fig:TCP_echo_server_first_code} viene modificato nella forma
+riportata in fig.~\ref{fig:TCP_echod_third}. In questo caso il socket su cui
+porsi in ascolto viene ottenuto (\texttt{\small 15--18}) da \func{sockbind}
+che si cura anche della eventuale risoluzione di un indirizzo specifico sul
+quale si voglia far ascoltare il server.
+
 
 
 \section{Le opzioni dei socket}
-\label{sec:TCP_sock_options}
+\label{sec:sock_options}
+
+Benché dal punto di vista del loro uso come canali di trasmissione di dati i
+socket siano trattati allo stesso modo dei file, associandoli a dei file
+descriptor, e utilizzando le varie funzioni di I/O su di questi, la normale
+interfaccia usata per la gestione dei file non è ovviamente sufficiente a
+poterne controllare tutte le caratteristiche, che variano tra l'altro a
+seconda del loro tipo. In questa sezione vedremo allora quali sono le funzioni
+dedicate alla gestione di tutte le caratteristiche specifiche dei vari tipi di
+socket, le cosiddette \textit{socket options}.
+
+
+\subsection{Le funzioni \func{setsockopt} e \func{getsockopt}}
+\label{sec:sock_setsockopt}
+
+
+
+
+Le due funzioni principali per gestire le caratteristiche specifiche dei vari
+tipi di socket sono \func{setsockopt} e \func{getsockopt}.
 
-Finora abbiamo trattato i socket nel loro comportamento più comune, è però
-possibile attivare alcune modalità diverse di funzionamento degli stessi
 
-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.
+\subsection{Le opzioni generiche}
+\label{sec:sock_generic_options}
+
+Anche se ciascun tipo di socket presenta una serie di caratteristiche
+particolari, gestite attraverso delle opzioni specifiche, ma esiste un insieme
+generico di opzioni che possono applicarsi a qualunque tipo di socket. 
+
 
 \section{Altre funzioni di controllo}
-\label{sec:TCP_sock_ctrl}
+\label{sec:sock_ctrl_func}
+
+Benché la maggior parte delle caratteristiche dei socket sia gestita
+attraverso le due funzioni \func{setsockopt} e \func{getsockopt}, alcune
+funzionalità possono essere impostate attraverso quelle che sono le funzioni
+classiche per il controllo delle proprietà dei file, cioè \func{fcntl} e
+\func{ioctl}. 
+
+
+\subsection{L'uso di \func{fcntl} per i socket}
+\label{sec:sock_fcntl}
+
+Abbiamo già trattato l'uso di \func{fcntl} in sez.~\ref{sec:file_fcntl}, dove
+però ne abbiamo descritto le funzionalità nell'ambito della sua applicazione a
+file descriptor associati a file normali; tratteremo qui invece il suo uso
+specifico quando la si impiega su file descriptor associati a dei socket.
+
 
+\subsection{L'uso di \func{ioctl} per i socket}
+\label{sec:sock_ioctl}
 
+Come per \func{fcntl} abbiamo trattato l'uso di \func{ioctl} in
+sez.~\ref{sec:file_ioctl}, dove ne abbiamo descritto le funzionalità
+nell'ambito dell'applicazione su file normali; tratteremo qui il suo uso
+specifico quando la si impiega su file descriptor associati a dei socket.
 
 
 
index 6890492..cca4933 100644 (file)
@@ -64,7 +64,7 @@ int main(int argc, char *argv[])
     int waiting = 0;
     int compat = 0;
     pid_t pid;
-    struct sockaddr_in serv_add, cli_add;
+    struct sockaddr_in cli_add;
     socklen_t len;
     char debug[MAXLINE], ipaddr[20];
     /*
@@ -116,7 +116,7 @@ int main(int argc, char *argv[])
        SignalRestart(SIGCHLD, HandSigCHLD);  /* restarting handler */
     }
     /* create and bind socket */
-    if ( (list_fd = sockbind(NULL, "echo", 6, SOCK_STREAM)) < 0) {
+    if ( (list_fd = sockbind(argv[optind], "echo", 6, SOCK_STREAM)) < 0) {
        return 1;
     }   
     /* release privileges and go daemon */
index 86c154f..6890492 100644 (file)
@@ -1,4 +1,4 @@
-/* TCP_echod_third.c
+/* TCP_echod.c
  * 
  * Copyright (C) 2001-2004 Simone Piccardi
  * 
@@ -20,7 +20,6 @@
  *
  * Program echod 
  * Elementary TCP server for echo service (port 7)
- * Third version, use sockbind
  *
  * Author: Simone Piccardi
  * Jun. 2001
@@ -117,8 +116,7 @@ int main(int argc, char *argv[])
        SignalRestart(SIGCHLD, HandSigCHLD);  /* restarting handler */
     }
     /* create and bind socket */
-    if ( (list_fd = sockbind(argv[optind], "echo", 6, SOCK_STREAM)) < 0) {
-       if (errno) perror("Socket creation error");
+    if ( (list_fd = sockbind(NULL, "echo", 6, SOCK_STREAM)) < 0) {
        return 1;
     }   
     /* release privileges and go daemon */