X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=socket.tex;h=46179b0d079715a0db63c5e43851fb693915f078;hp=fafe08ebd1610b00eb7e5120b7aea0ad2fbf2d03;hb=59ee032c64ce1caa37bfc311f63219a52efe21d4;hpb=5854d47465c992d90b2dd0ebc18417f9a9bef377 diff --git a/socket.tex b/socket.tex index fafe08e..46179b0 100644 --- a/socket.tex +++ b/socket.tex @@ -572,13 +572,13 @@ cosiddetta notazione \textit{dotted-decimal}, (cio 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)} @@ -636,7 +636,7 @@ negativo e settano la variabile \texttt{errno} al valore \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 @@ -649,35 +649,161 @@ negativo e settano la variabile \texttt{errno} al valore \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 + +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 + +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} +