X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=sockctrl.tex;h=62fd3d7037692a521a027423fa3d9f40f293cf9a;hp=b86644240d8b0e78ae0ef923b354617fec6114f1;hb=f8f72700e2402e0753124978199ab8801667bfd1;hpb=839d84a7794ebbde7edafb5b0f30fc3455b26f7b diff --git a/sockctrl.tex b/sockctrl.tex index b866442..62fd3d7 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -1199,16 +1199,18 @@ forniscono una interfaccia sufficientemente generica. Inoltre in genere quando si ha a che fare con i socket non esiste soltanto il problema della risoluzione del nome che identifica la macchina, ma anche quello del servizio a cui ci si vuole rivolgere. Per questo motivo con lo -standard Posix 1003.1-2001 sono state indicate come deprecate le varie +standard POSIX 1003.1-2001 sono state indicate come deprecate le varie funzioni \func{gethostbyaddr}, \func{gethostbyname}, \var{getipnodebyname} e \var{getipnodebyaddr} ed è stata introdotta una interfaccia completamente nuova. -La prima funzione di questa interfaccia è \funcd{getaddrinfo}, che combina le +La prima funzione di questa interfaccia è \funcd{getaddrinfo},\footnote{la + funzione è definita, insieme a \func{getnameinfo} che vedremo più avanti, + nell'\href{http://www.ietf.org/rfc/rfc2553.txt} {RFC~2553}.} che combina le funzionalità delle precedenti \func{getipnodebyname}, \func{getipnodebyaddr}, \func{getservbyname} e \func{getservbyport}, consentendo di ottenere contemporaneamente sia la risoluzione di un indirizzo simbolico che del nome -un servizio; il suo prototipo è: +di un servizio; il suo prototipo è: \begin{functions} \headdecl{netdb.h} \headdecl{sys/socket.h} @@ -1230,16 +1232,16 @@ forma \textit{dotted-decimal} per IPv4 o in formato esadecimale per IPv6. Si può anche specificare il nome di una rete invece che di una singola macchina. Il secondo argomento, \param{service}, specifica invece il nome del servizio che si intende risolvere. Per uno dei due argomenti si può anche usare il -valore \const{NULL}, nel qual caso la risoluzione verrà effettuata utilizzando -soltantoo sulla base del valore dell'altro. +valore \const{NULL}, nel qual caso la risoluzione verrà effettuata soltanto +sulla base del valore dell'altro. Il terzo argomento, \param{hints}, deve essere invece un puntatore ad una struttura \struct{addrinfo} usata per dare dei \textsl{suggerimenti} al procedimento di risoluzione riguardo al protocollo o del tipo di socket che si -intenderà utilizzare; la funzione infatti permette di effettuare ricerche -generiche sugli indirizzi, usando sia IPv4 che IPv6, e richiedere risoluzioni -sui nomi dei servizi indipendentemente dal protocollo (ad esempio TCP o UDP) -che questi possono utilizzare. +intenderà utilizzare; \func{getaddrinfo} infatti permette di effettuare +ricerche generiche sugli indirizzi, usando sia IPv4 che IPv6, e richiedere +risoluzioni sui nomi dei servizi indipendentemente dal protocollo (ad esempio +TCP o UDP) che questi possono utilizzare. \begin{figure}[!htb] \footnotesize \centering @@ -1257,7 +1259,7 @@ La struttura \struct{addrinfo}, la cui definizione\footnote{la definizione per il campo \var{ai\_addrlen}, qui viene usata quanto previsto dallo standard POSIX, in cui viene utilizzato \type{socklen\_t}; i due tipi di dati sono comunque equivalenti.} è riportata in -fig.~\ref{fig:sock_addrinfo_struct} viene usata sia in ingresso, per passare +fig.~\ref{fig:sock_addrinfo_struct}, viene usata sia in ingresso, per passare dei valori di controllo alla funzione, che in uscita, per ricevere i risultati. Il primo campo, \var{ai\_flags}, è una maschera binaria di bit che permettono di controllare le varie modalità di risoluzione degli indirizzi, @@ -1272,10 +1274,10 @@ Tutti i campi seguenti vengono usati soltanto in uscita; il campo \var{ai\_addrlen} indica la dimensione della struttura degli indirizzi ottenuta come risultato, il cui contenuto sarà memorizzato nella struttura \struct{sockaddr} posta all'indirizzo puntato dal campo \var{ai\_addr}. Il -campo \var{ai\_canonname} è il puntatore alla stringa contenente il nome +campo \var{ai\_canonname} è un puntatore alla stringa contenente il nome canonico della macchina, ed infine, quando la funzione restituisce più di un -risultato, \var{ai\_next} è il puntatore alla struttura \struct{addrinfo} -successiva della lista. +risultato, \var{ai\_next} è un puntatore alla successiva struttura +\struct{addrinfo} della lista. Ovviamente non è necessario dare dei suggerimenti in ingresso, ed usando \const{NULL} come valore per l'argomento \param{hints} si possono compiere @@ -1288,10 +1290,10 @@ I due campi \var{ai\_family} e \var{ai\_socktype} prendono gli stessi valori degli analoghi argomenti della funzione \func{socket}; in particolare per \var{ai\_family} si possono usare i valori di tab.~\ref{tab:net_pf_names} ma sono presi in considerazione solo \const{PF\_INET} e \const{PF\_INET6}, mentre -se non si vuole specificare questo nessuna famiglia di indirizzi si può usare -il valore \const{PF\_UNSPEC}. Allo stesso modo per \var{ai\_socktype} si -possono usare i valori illustrati sez.~\ref{sec:sock_type} per indicare per -quale tipo di socket si vuole risolvere il servizio indicato, anche se i soli +se non si vuole specificare nessuna famiglia di indirizzi si può usare il +valore \const{PF\_UNSPEC}. Allo stesso modo per \var{ai\_socktype} si possono +usare i valori illustrati in sez.~\ref{sec:sock_type} per indicare per quale +tipo di socket si vuole risolvere il servizio indicato, anche se i soli significativi sono \const{SOCK\_STREAM} e \const{SOCK\_DGRAM}; in questo caso, se non si vuole effettuare nessuna risoluzione specifica, si potrà usare un valore nullo. @@ -1359,12 +1361,12 @@ bit della maschera. Come ultimo argomento di \func{getaddrinfo} deve essere passato un puntatore ad una variabile (di tipo puntatore ad una struttura \struct{addrinfo}) che -verrà utilizzata dalla funzione per restituire (come \textit{value result +verrà utilizzata dalla funzione per riportare (come \textit{value result argument}) i propri risultati. La funzione infatti è rientrante, ed alloca autonomamente tutta la memoria necessaria in cui verranno riportati i -risultati della risoluzione. La funzione restituisce in \param{res} il -puntatore alla prima di una \textit{linked list} di strutture di tipo -\struct{addrinfo} contenenti tutte le informazioni ottenute. +risultati della risoluzione. La funzione scriverà in \param{res} il puntatore +iniziale ad una \textit{linked list} di strutture di tipo \struct{addrinfo} +contenenti tutte le informazioni ottenute. La funzione restituisce un valore nullo in caso di successo, o un codice in caso di errore. I valori usati come codice di errore sono riportati in @@ -1396,7 +1398,8 @@ corrispondente altri tipi di socket. \\ \const{EAI\_ADDRFAMILY}& la rete richiesta non ha nessun indirizzo di rete per la famiglia di indirizzi specificata. \\ - \const{EAI\_NODATA} & la . \\ + \const{EAI\_NODATA} & la macchina specificata esiste, ma non ha nessun + indirizzo di rete definito. \\ \const{EAI\_MEMORY} & è stato impossibile allocare la memoria necessaria alle operazioni. \\ \const{EAI\_FAIL} & il DNS ha restituito un errore di risoluzione @@ -1493,11 +1496,10 @@ canonico che La scansione viene ripetuta (\texttt{\small 14}) fintanto che si ha un puntatore valido. La selezione principale è fatta sul campo \var{ai\_family}, che stabilisce a quale famiglia di indirizzi fa riferimento la struttura in -esame. Le possibilità sono due, un indirizzo IPv4 (\texttt{\small 15}) o IPv6 -(\texttt{\small 21}), se nessuna delle due si verifica si provvede -(\texttt{\small 27--30}) a stampare un messaggio di errore ed -uscire.\footnote{questa eventualità non dovrebbe mai verificarsi, almeno - fintanto che la funzione \func{getaddrinfo} lavora correttamente.} +esame. Le possibilità sono due, un indirizzo IPv4 o IPv6, se nessuna delle due +si verifica si provvede (\texttt{\small 27--30}) a stampare un messaggio di +errore ed uscire.\footnote{questa eventualità non dovrebbe mai verificarsi, + almeno fintanto che la funzione \func{getaddrinfo} lavora correttamente.} Per ciascuno delle due possibili famiglie di indirizzi si estraggono le informazioni che poi verranno stampate alla fine del ciclo (\texttt{\small @@ -1524,7 +1526,7 @@ puntatore al campo contenente l'indirizzo IP nella struttura puntata dal campo Una volta estratte dalla struttura \struct{addrinfo} tutte le informazioni relative alla risoluzione richiesta e stampati i relativi valori, l'ultimo -passo è (\texttt{\small 34}) estrarre da \var{ai\_next} l'indirizzo della +passo (\texttt{\small 34}) è di estrarre da \var{ai\_next} l'indirizzo della eventuale successiva struttura presente nella lista e ripetere il ciclo, fin tanto che, completata la scansione, questo avrà un valore nullo e si potrà terminare (\texttt{\small 36}) il programma. @@ -1577,6 +1579,86 @@ si copiano anche tutti i dati presenti agli indirizzi contenuti nella struttura \struct{addrinfo}, perché una volta disallocati i dati con \func{freeaddrinfo} questi non sarebbero più disponibili. +Anche la nuova intefaccia definita da POSIX prevede una nuova funzione per +eseguire la risoluzione inversa e determinare nomi di servizi e di dominio +dati i rispettivi valori numerici. La funzione che sostituisce le varie +\func{gethostbyname}, \func{geipnodebyname} e \func{getservname} è +\funcd{getnameinfo}, ed il suo prototipo è: +\begin{functions} + \headdecl{sys/socket.h} + \headdecl{netdb.h} + + \funcdecl{int getnameinfo(const struct sockaddr *sa, socklen\_t salen, char + *host, size\_t hostlen, char *serv, size\_t servlen, int flags)} + + Risolve il contenuto di una struttura degli indirizzi in maniera + indipendente dal protocollo. + + \bodydesc{La funzione restituisce 0 in caso di successo e un codice di + errore diverso da zero altrimenti.} +\end{functions} + +La principale caratteristica di \func{getnameinfo} è che la funzione è in +grado di eseguire una risoluzione inversa in maniera indipendente dal +protocollo; il suo primo argomento \param{sa} infatti è il puntatore ad una +struttura degli indirizzi generica, che può contenere sia indirizzi IPv4 che +IPv6, la cui dimensione deve comunque essere specificata con l'argomento +\param{salen}. + +I risultati della funzione saranno restituiti nelle due stringhe puntate da +\param{host} e \param{serv}, che dovranno essere state precedentemente +allocate per una lunghezza massima che deve essere specificata con gli altri +due argomenti \param{hostlen} e \param{servlen}. Si può, quando non si è +interessati ad uno dei due, passare il valore \const{NULL} come argomento, +così che la corrispondente informazione non verrà richiesta. Infine l'ultimo +argomento \param{flags} è una maschera binaria i cui bit consentono di +impostare le modalità con cui viene eseguita la ricerca, e deve essere +specificato attraverso l'OR aritmetico dei valori illustrati in +tab.~\ref{tab:getnameinfo_flags}. + +\begin{table}[!htb] + \centering + \footnotesize + \begin{tabular}[c]{|l|p{10cm}|} + \hline + \textbf{Costante} & \textbf{Significato} \\ + \hline + \hline + \const{NI\_NOFQDN} & richiede che venga restituita solo il nome della + macchina all'interno del dominio al posto del + nome completo (FQDN).\\ + \const{NI\_NUMERICHOST}& richiede che venga restituita la forma numerica + dell'indirizzo (questo succede sempre se il nome + non può essere ottenuto).\\ + \const{NI\_NAMEREQD} & richiede la restituzione di un errore se il nome + non può essere risolto.\\ + \const{NI\_NUMERICSERV}& richiede che il servizio venga restituito in + forma numerica (attraverso il numero di porta).\\ + \const{NI\_DGRAM} & richiede che venga restituito il nome del + servizio su UDP invece che quello su TCP per quei + pichi servizi (porte 512-214) che soni diversi + nei due protocolli.\\ + \hline + \end{tabular} + \caption{Costanti associate ai bit dell'argomento \param{flags} della + funzione \func{getnameinfo}.} + \label{tab:getnameinfo_flags} +\end{table} + +La funzione ritorna zero in caso di successo, e scrive i propri risultati agli +indirizzi indicati dagli argomenti \param{host} e \param{serv} come stringhe +terminate dal carattere NUL, a meno che queste non debbano essere troncate +qualora la loro dimensione ecceda quelle specificate dagli argomenti +\param{hostlen} e \param{servlen}. Sono comunque definite le due costanti +\const{NI\_MAXHOST} e \const{NI\_MAXSERV}\footnote{le due costanti sono + definite in \file{netdb.h} ed hanno rispettivamente il valore 1024 e 12.} +che possono essere utilizzate come limiti massimi. In caso di errore viene +restituito invece un codice che assume gli stessi valori illustrati in +tab.~\ref{tab:addrinfo_error_code}. + +A questo punto possiamo fornire degli esempi di utilizzo diretto della nuova +interfaccia, adottandola per rendere i nostri client + \section{Le opzioni dei socket} \label{sec:TCP_sock_options} @@ -1585,7 +1667,7 @@ Finora abbiamo trattato i socket nel loro comportamento pi 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 + 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.