X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=elemtcp.tex;h=a2e77f9c86ca273db11957889223a728b0ae4e86;hp=94612fa7759e2fd4415015a93c33a0dca7adfaf2;hb=597e090affe725734ce571d29d6fae420f2a5d75;hpb=caa4d2b308da07b9522599555d07db6f67351601 diff --git a/elemtcp.tex b/elemtcp.tex index 94612fa..a2e77f9 100644 --- a/elemtcp.tex +++ b/elemtcp.tex @@ -3,9 +3,10 @@ In questo capitolo inizieremo ad approndire 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 \ref{sec:net_cli_sample} -e \ref{sec:net_serv_sample}), previa una descrizione delle principali -caratteristiche del funzionamento di una connessione TCP. +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. La seconda parte del capitolo sarà poi dedicata alla scrittura di una prima semplice applicazione client/server completa, che implementi il servizio @@ -31,10 +32,10 @@ l'uso del programma \texttt{netstat}. Il processo che porta a creare una connessione TCP è chiamato \textit{three way handushake}; la successione tipica degli eventi (la stessa che si verifica utilizzando il codice dei due precedenti esempi elementari -\ref{fig:net_cli_code} e \ref{fig:net_serv_code}) che porta alla creazione di -una connessione è la seguente: +\figref{fig:net_cli_code} e \figref{fig:net_serv_code}) che porta alla +creazione di una connessione è la seguente: -\begin{itemize} +\begin{enumerate} \item Il server deve essere preparato per accettare le connessioni in arrivo; il procedimento si chiama \textsl{apertura passiva} del socket (in inglese \textit{passive open}); questo viene fatto chiamando la sequenza di funzioni @@ -55,7 +56,7 @@ una connessione \texttt{SYN}, \texttt{ACK}, \texttt{URG}, \texttt{FIN}, alcuni di essi, come \texttt{SYN} (che sta per \textit{sincronize}) corrispondono a funzioni particolari del protocollo e danno il nome al segmento, (per - maggiori dettagli vedere \ref{cha:tcp_protocol})}, in sostanza viene + maggiori dettagli vedere \capref{cha:tcp_protocol})}, in sostanza viene inviato al server un pacchetto IP che contiene solo gli header IP e TCP (con il numero di sequenza iniziale e il flag \texttt{SYN}) e le opzioni di TCP. @@ -70,7 +71,7 @@ una connessione \texttt{SYN} del server inviando un \texttt{ACK}. Alla ricezione di quest'ultimo la funzione \texttt{accept} del server ritorna e la connessione è stabilita. -\end{itemize} +\end{enumerate} Il procedimento viene chiamato \textit{three way handshake} dato che per realizzarlo devono essere scambiati tre segmenti. In \nfig\ si è @@ -126,7 +127,7 @@ regolare la connessione. Normalmente vengono usate le seguenti opzioni: connesione corrente. È possibile leggere e scrivere questo valore attraverso l'opzione del socket \texttt{TCP\_MAXSEG}. -\item \textit{window scale option} come spiegato in \ref{cha:tcp_protocol} il +\item \textit{window scale option} come spiegato in \capref{cha:tcp_protocol} il protocollo TCP implementa il controllo di flusso attraverso una \textsl{finestra annunciata} (\textit{advertized window}) con la quale ciascun capo della comunicazione dichiara quanto spazio disponibile ha in @@ -164,8 +165,8 @@ elevati. In ogni caso linux supporta pienamente entrambe le opzioni. Mentre per creare una connessione occorre un interscambio di tre segmenti, la procedura di chiusura ne richede quattro; ancora una volta si può fare -riferimento al codice degli esempi \ref{fig:net_cli_code} e -\ref{fig:net_serv_code}, in questo caso la successione degli eventi è la +riferimento al codice degli esempi \figref{fig:net_cli_code} e +\figref{fig:net_serv_code}, in questo caso la successione degli eventi è la seguente: \begin{enumerate} @@ -185,7 +186,7 @@ seguente: \item Dopo un certo tempo anche il secondo processo chiamerà la funzione \texttt{close} sul proprio socket, causando l'emissione di un altro segmento FIN. - + \item L'altro capo della connessione riceverà il FIN conclusivo e risponderà con un ACK. \end{enumerate} @@ -218,17 +219,17 @@ pi La emissione del FIN avviene quando il socket viene chiuso, questo però non avviene solo per la chiamata della funzione \texttt{close} (come in -\ref{fig:net_serv_code}), ma anche alla terminazione di un processo (come in -\ref{fig:net_cli_code}). Questo vuol dire ad esempio che se un processo viene -terminato da un segnale tutte le connessioni aperte verranno chiuse. +\figref{fig:net_serv_code}), ma anche alla terminazione di un processo (come +in \figref{fig:net_cli_code}). Questo vuol dire ad esempio che se un processo +viene terminato da un segnale tutte le connessioni aperte verranno chiuse. Infine è da sottolineare che, benché nella figura (e nell'esempio che vedremo -in \ref{sec:TCPel_echo_example}) sia il client ad eseguire la chiusura attiva, -nella realtà questa può essere eseguita da uno qualunque dei due capi della -comunicazione (come in fatto in precedenza da \ref{fig:net_serv_code}), e -benché quello del client sia il caso più comune ci sono alcuni servizi, il -principale dei quali è l'HTTP, per i quali è il server ad effettuare la -chiusura attiva. +in \secref{sec:TCPel_echo_example}) sia il client ad eseguire la chiusura +attiva, nella realtà questa può essere eseguita da uno qualunque dei due capi +della comunicazione (come in fatto in precedenza da +\figref{fig:net_serv_code}), e benché quello del client sia il caso più comune +ci sono alcuni servizi, il principale dei quali è l'HTTP, per i quali è il +server ad effettuare la chiusura attiva. \subsection{Un esempio di connessione} \label{sec:TCPel_conn_dia} @@ -242,26 +243,26 @@ che vengono riportati del comando \texttt{netstat} nel campo \textit{State}. Una descrizione completa del funzionamento del protocollo va al di là degli obiettivi di questo libro; un approfondimento sugli aspetti principali si -trova in \ref{cha:tcp_protocol}, ma per una trattazione esauriente il miglior +trova in \capref{cha:tcp_protocol}, ma per una trattazione esauriente il miglior riferimento resta (FIXME citare lo Stevens); qui ci limiteremo a descrivere brevemente un semplice esempio di connessione e le transizioni che avvengono nei due casi appena citati (creazione e terminazione della connessione). -In assenza di connessione lo stato del TCP è \textsl{CLOSED}; quando una +In assenza di connessione lo stato del TCP è \texttt{CLOSED}; quando una applicazione esegue una apertura attiva il TCP emette un SYN e lo stato -diventa \textsl{SYN\_SENT}; quando il TCP riceve la risposta del SYN$+$ACK -emette un ACK e passa allo stato \textsl{ESTABLISHED}; questo è lo stato +diventa \texttt{SYN\_SENT}; quando il TCP riceve la risposta del SYN$+$ACK +emette un ACK e passa allo stato \texttt{ESTABLISHED}; questo è lo stato finale in cui avviene la gran parte del trasferimento dei dati. Dal lato server in genere invece il passaggio che si opera con l'apertura -passiva è quello di portare il socket dallo stato \textsl{CLOSED} allo -stato \textsl{LISTEN} in cui vengono accettate le connessioni. +passiva è quello di portare il socket dallo stato \texttt{CLOSED} allo +stato \texttt{LISTEN} in cui vengono accettate le connessioni. -Dallo stato \textsl{ESTABLISHED} si può uscire in due modi; se un'applicazione +Dallo stato \texttt{ESTABLISHED} si può uscire in due modi; se un'applicazione chiama la \texttt{close} prima di aver ricevuto un end of file (chiusura -attiva) la transizione è verso lo stato \textsl{FIN\_WAIT\_1}; se invece -l'applicazione riceve un FIN nello stato \textsl{ESTABLISHED} (chiusura -passiva) la transizione è verso lo stato \textsl{CLOSE\_WAIT}. +attiva) la transizione è verso lo stato \texttt{FIN\_WAIT\_1}; se invece +l'applicazione riceve un FIN nello stato \texttt{ESTABLISHED} (chiusura +passiva) la transizione è verso lo stato \texttt{CLOSE\_WAIT}. In \nfig\ è riportato lo schema dello scambio dei pacchetti che avviene per una un esempio di connessione, insieme ai vari stati che il protocollo viene @@ -289,9 +290,9 @@ caso contrario si avrebbe prima l'emissione di un ACK e poi l'invio della risposta. Infine si ha lo scambio dei quattro segmenti che terminano la connessione -secondo quanto visto in \ref{sec:TCPel_conn_term}; si noti che il capo della +secondo quanto visto in \secref{sec:TCPel_conn_term}; si noti che il capo della connessione che esegue la chiusura attiva entra nello stato -\textsl{TIME\_WAIT} su cui torneremo fra poco. +\texttt{TIME\_WAIT} su cui torneremo fra poco. È da notare come per effettuare uno scambio di due pacchetti (uno di richiesta e uno di risposta) il TCP necessiti di ulteriori otto segmenti, se invece si @@ -329,7 +330,7 @@ La MSL sulla rete; questo tempo è limitato perché ogni pacchetto IP può essere ritrasmesso dai router un numero massimo di volte (detto \textit{hop limit}). Il numero di ritrasmissioni consentito è indicato dal campo TTL dell'header di -IP (per maggiori dettagli vedi \ref{sec:appA_xxx}), e viene decrementato ad +IP (per maggiori dettagli vedi \secref{sec:appA_xxx}), e viene decrementato ad ogni passaggio da un router; quando si annulla il pacchetto viene scartato. Siccome il numero è ad 8 bit il numero massimo di ``salti'' è di 255, pertanto anche se il TTL (da \textit{time to live}) non è propriamente un limite sul @@ -338,16 +339,16 @@ pi Ogni implementazione del TCP deve scegliere un valore per la MSL (l'RFC1122 raccomanda 2 minuti, linux usa 30 secondi), questo comporta una durata dello -stato \textsl{TIME\_WAIT} che a seconda delle implementazioni può variare fra +stato \texttt{TIME\_WAIT} che a seconda delle implementazioni può variare fra 1 a 4 minuti. Lo stato \texttt{TIME\_WAIT} viene utilizzato dal protocollo per due motivi principali: -\begin{itemize} +\begin{enumerate} \item implementare in maniera affidabile la terminazione della connessione in entrambe le direzioni. \item consentire l'eliminazione dei segmenti duplicati dalla rete. -\end{itemize} +\end{enumerate} Il punto è che entrambe le ragioni sono importanti, anche se spesso si fa riferimento solo alla prima; ma è solo se si tiene conto della seconda che si @@ -422,7 +423,7 @@ In un ambiente multitasking in un dato momento pi usare sia UDP che TCP, e ci devono poter essere più connessioni in contemporanea. Per poter tenere distinte le diverse connessioni entrambi i protocolli usano i \textsl{numeri di porta}, che fanno parte, come si può -vedere in \ref{sec:sock_sa_ipv4} e \ref{sec:sock_sa_ipv6} pure delle strutture +vedere in \secref{sec:sock_sa_ipv4} e \secref{sec:sock_sa_ipv6} pure delle strutture degli indirizzi del socket. Quando un client contatta un server deve poter identificare con quale dei vari @@ -508,7 +509,7 @@ campi \textit{Local Address} e \textit{Foreing Address}. Per capire meglio l'uso delle porte e come vengono utilizzate quando si ha a che fare con un'applicazione client/server (come quella che scriveremo in -\ref{sec:TCPel_echo_example}) esaminaremo cosa accade con le connessioni nel +\secref{sec:TCPel_echo_example}) esaminaremo cosa accade con le connessioni nel caso di un server TCP che deve gestire connessioni multiple. Se esguiamo un \texttt{netstat} su una macchina di prova (che supponiamo avere @@ -600,14 +601,14 @@ alla porta 21101 al secondo. In questa sezione descriveremo in dettaglio le varie funzioni necessarie per l'uso dei socket TCP già citate in precedenza (e utilizzate nei due esempi -\ref{sec:net_cli_sample} e \ref{sec:net_serv_sample}) con l'eccezione della -funzione \texttt{socket} che è già stata esaminata in dettaglio in -\ref{sec:sock_socket}. +\secref{sec:net_cli_sample} e \secref{sec:net_serv_sample}) con l'eccezione +della funzione \texttt{socket} che è già stata esaminata in dettaglio in +\secref{sec:sock_socket}. In \nfig\ abbiamo un tipico schema di funzionamento di un'applicazione client-server che usa i socket TCP: prima il server viene avviato ed in seguito il client si connette, in questo caso, a differenza di quanto accadeva -con gli esempi elementari del Cap.~\ref{cha:network} si assume che sia il +con gli esempi elementari del Cap.~\capref{cha:network} si assume che sia il client ad effettuare delle richieste a cui il server risponde, il client notifica poi di avere concluso inviando un end-of-file a cui il server risponderà anche lui chiudendo la connessione per aspettarne una nuova. @@ -621,7 +622,7 @@ risponder \end{figure} Useremo questo schema per l'esempio di implementazione del servizio -\texttt{echo} che illustreremo in \ref{sec:TCPel_echo_example}. +\texttt{echo} che illustreremo in \secref{sec:TCPel_echo_example}. \subsection{La funzione \texttt{bind}} @@ -633,29 +634,27 @@ cio server per specificare la porta (e gli eventuali indirizzi locali) su cui poi ci si porrà in ascolto. -Il prototipo della funzione, definito in \texttt{sys/socket.h}, è il seguente: +Il prototipo della funzione è il seguente: -\begin{itemize} -\item \texttt{int bind(int sockfd, const struct sockaddr *serv\_addr, - socklen\_t addrlen) } +\begin{prototype}{sys/socket.h} +{int bind(int sockfd, const struct sockaddr *serv\_addr, socklen\_t addrlen)} Il primo argomento è un file descriptor ottenuto da una precedente chiamata a \texttt{socket}, mentre il secondo e terzo argomento sono rispettivamente l'indirizzo (locale) del socket e la dimensione della struttura che lo - contiene, secondo quanto già trattato in \ref{sec:sock_sockaddr}. + contiene, secondo quanto già trattato in \secref{sec:sock_sockaddr}. La funzione restituisce zero in caso di successo e -1 per un errore, in caso di errore. La variabile \texttt{errno} viene settata secondo i seguenti codici di errore: - \begin{itemize} + \begin{errlist} \item \texttt{EBADF} Il file descriptor non è valido. \item \texttt{EINVAL} Il socket ha già un indirizzo assegnato. \item \texttt{ENOTSOCK} Il file descriptor non è associato ad un socket. \item \texttt{EACCESS} Si è cercato di usare un indirizzo riservato senza essere root. - \end{itemize} - -\end{itemize} + \end{errlist} +\end{prototype} Con il TCP la chiamata \texttt{bind} permette di specificare l'indirizzo, la porta, entrambi o nessuno dei due. In genere i server utilizzano una porta @@ -685,7 +684,7 @@ client. Per specificare un indirizzo generico con IPv4 si usa il valore \texttt{INADDR\_ANY}, il cui valore, come visto anche negli esempi precedenti -è pari a zero, nell'esempio \ref{fig:net_serv_sample} si è usata +è pari a zero, nell'esempio \figref{fig:net_serv_sample} si è usata un'assegnazione immediata del tipo: \begin{verbatim} serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ @@ -714,22 +713,20 @@ di effettuare una assegnazione del tipo: \label{sec:TCPel_func_connect} La funzione \texttt{connect} è usata da un client TCP per stabilire la -connessione con un server TCP, il prototipo della funzione, definito in -\texttt{sys/socket.h}, è il seguente: +connessione con un server TCP, il prototipo della funzione è il seguente: -\begin{itemize} -\item \texttt{int connect(int sockfd, const struct sockaddr *serv\_addr, - socklen\_t addrlen) } +\begin{prototype}{sys/socket.h} +{int connect(int sockfd, const struct sockaddr *serv\_addr, socklen\_t addrlen)} Il primo argomento è un file descriptor ottenuto da una precedente chiamata a \texttt{socket}, mentre il secondo e terzo argomento sono rispettivamente l'indirizzo e la dimensione della struttura che contiene l'indirizzo del - socket, già descritta in \ref{sec:sock_sockaddr}. + socket, già descritta in \secref{sec:sock_sockaddr}. La funzione restituisce zero in caso di successo e -1 per un errore, in caso di errore. La variabile \texttt{errno} viene settata secondo i seguenti codici di errore: - \begin{itemize} + \begin{errlist} \item \texttt{EBADF} Il file descriptor non è valido. \item \texttt{EFAULT} L'indirizzo della struttura di indirizzi è al di fuori dello spazio di indirizzi dell'utente. @@ -750,13 +747,13 @@ connessione con un server TCP, il prototipo della funzione, definito in \item \texttt{EACCESS, EPERM} Si è tentato di eseguire una connessione ad un indirizzo broacast senza che il socket fosse stato abilitato per il broadcast. - \end{itemize} -\end{itemize} + \end{errlist} +\end{prototype} La struttura dell'indirizzo deve essere inizializzata con l'indirizzo IP e il numero di porta del server a cui ci si vuole connettere, come mostrato -nell'esempio \ref{sec:net_cli_sample} usando le funzioni illustrate in -\ref{sec:sock_addr_func}. +nell'esempio \secref{sec:net_cli_sample} usando le funzioni illustrate in +\secref{sec:sock_addr_func}. Nel caso di socket TCP la funzione \texttt{connect} avvia il three way handshake, e ritorna solo quando la connessione è stabilita o si è verificato @@ -802,7 +799,7 @@ da errori o problemi nella chiamata della funzione sono le seguenti: \end{enumerate} Se si fa riferimento al diagramma degli stati del TCP riportato in -\ref{fig:appB:tcp_state_diag} la funzione \texttt{connect} porta un socket +\figref{fig:appB:tcp_state_diag} la funzione \texttt{connect} porta un socket dallo stato \texttt{CLOSED} (lo stato iniziale in cui si trova un socket appena creato) prima allo stato \texttt{SYN\_SENT} e poi, al ricevimento del ACK, nello stato \texttt{ESTABLISHED}. Se invece la connessione fallisce il @@ -821,23 +818,146 @@ necessario effettuare una \texttt{bind}. La funzione \texttt{listen} è usata per usare un socket in modalità passiva, cioè, come dice il nome, per metterlo in ascolto di eventuali connessioni; in sostanza l'effetto della funzione è di portare il socket dallo stato -\texttt{CLOSED} a quello \texttt{LISTEN}. +\texttt{CLOSED} a quello \texttt{LISTEN}. In genere si chiama la funzione in +un server dopo le chiamate a \texttt{socket} e \texttt{bind} e prima della +chiamata ad \texttt{accept}. Il prototipo della funzione come definito dalla +man page è: + +\begin{prototype}{sys/socket.h}{int listen(int sockfd, int backlog)} + + La funzione pone il socket specificato da \texttt{sockfd} in modalità + passiva e predispone una coda per le connessioni in arrivo di lunghezza pari + a \texttt{backlog}. La funzione si può applicare solo a socket di tipo + \texttt{SOCK\_STREAM} o \texttt{SOCK\_SEQPACKET}. -\begin{prototype}{int listen(int sockfd, int backlog)} + La funzione restituisce 0 in caso di successo e -1 in caso di errore. I + codici di errore restituiti in \texttt{errno} sono i seguenti: \begin{errlist} \item \texttt{EBADF} L'argomento \texttt{sockfd} non è un file descriptor valido. \item \texttt{ENOTSOCK} L'argomento \texttt{sockfd} non è un socket. - \item \texttt{EOPNOTSUPP} The socket is not of a type that supports the lis­ - ten operation. + \item \texttt{EOPNOTSUPP} Il socket è di un tipo che non supporta questa + operazione. \end{errlist} \end{prototype} +Il parametro \texttt{backlog} indica il numero massimo di connessioni pendenti +accettate; se esso viene ecceduto il client riceverà una errore di tipo +\texttt{ECONNREFUSED}, o se il protocollo, come nel caso del TCP, supporta la +ritrasmissione, la richiesta sarà ignorata in modo che la connessione possa +essere ritentata. + +Per capire meglio il significato di tutto ciò occorre approfondire la modalità +con cui il kernel tratta le connessioni in arrivo. Per ogni socket in ascolto +infatti vengono mantenute due code: +\begin{enumerate} +\item Una coda delle connessioni incomplete (\textit{incomplete connection + queue} che contiene una entrata per ciascun SYN arrivato per il quale si + sta attendendo la conclusione del three-way handshake. Questi socket sono + tutti nello stato \texttt{SYN\_RECV}. +\item Una coda delle connessioni complete (\textit{complete connection queue} + che contiene una entrata per ciascuna connessione per le quali il three-way + handshake è stato completato ma ancora \texttt{accept} non è ritornata. +\end{enumerate} + +Lo schema di funzionamento è descritto in \nfig, quando arriva un SYN da un +client il server crea una nuova entrata nella coda delle connessioni +incomplete, e poi risponde con il SYN$+$ACK. La entrata resterà nella coda +delle connessioni incomplete fino al ricevimento dell'ACK dal client o fino ad +un timeout. Nel caso di completamento del three-way handshake l'entrata viene +sostata nella coda delle connessioni complete. Quando il processo chiama la +funzione \texttt{accept} (vedi \secref{sec:TCPel_func_accept}) la prima +entrata nella coda delle connessioni complete è passata al programma, o, se la +coda è vuota, il processo viene posto in attesa e risvegliato all'arrivo della +prima connessione completa. + +Storicamente il valore del parametro \texttt{backlog} era corrispondente al +massimo valore della somma del numero di entrate possibili per ciascuna di +dette code. Stevens riporta che BSD ha sempre applicato un fattore di 1.5 al +valore, e provvede una tabella con i risultati ottenuti con vari kernel, +compreso linux 2.0, che mostrano le differenze fra diverse implementazioni. + +Ma in linux il significato di questo valore è cambiato a partire dal kernel +2.2 per prevenire l'attacco chiamato \texttt{syn flood}. Questo si basa +sull'emissione da parte dell'attaccante di un grande numero di pacchetti SYN +indirizzati verso una porta forgiati con indirizzo IP fasullo \footnote{con la + tecnica che viene detta \textit{ip spoofing}} così che i SYN$+$ACK vanno +perduti la coda delle connessioni incomplete viene saturata, impedendo di +fatto le connessioni. + +Per ovviare a questo il significato del \texttt{backlog} è stato cambiato a +significare la lunghezza della coda delle connessioni complete. La lunghezza +della coda delle connessioni incomplete può essere ancora controllata usando +la \texttt{sysctl} o scrivendola direttamente in +\texttt{/proc/sys/net/ipv4/tcp\_max\_syn\_backlog}. Quando si attiva la +protezione dei syncookies però (con l'opzione da compilare nel kernel e da +attivare usando \texttt{/proc/sys/net/ipv4/tcp\_syncookies}) questo valore +viene ignorato e non esiste più un valore massimo. + +La scelta storica per il valore di questo parametro è di 5, e alcuni vecchi +kernel non supportavano neanche valori superiori, ma la situazione corrente è +molto cambiata dagli anni '80 e con server web che possono sopportare diversi +milioni di connessioni al giorno un tale valore non è più adeguato. Non esiste +comunque una risposta univoca per la scelta del valore, per questo non +conviene specificare questo valore con una costante (il cui cambiamento +richiederebbe la ricompilazione del server) ma usare piuttosto una variabile +di ambiente (vedi \secref{sec:xxx_env_var}). Lo Stevens tratta accuratamente +questo argomento, con esempi presi da casi reali su web server, ed in +particolare evidenzia come non sia più vero che la ragione della coda è quella +di gestire il caso in cui il server è occupato fra chiamate successive alla +\texttt{accept} (per cui la coda più occupata sarebbe quella delle connessioni +compeltate), ma è invece necessaria a gestire la presenza di un gran numero di +SYN in attesa di completare il three-way handshake. + +Come accennato nel caso del TCP se un SYN arriva con tutte le code piene, il +pacchetto sarà ignorato. Questo viene fatto perché la condizione delle code +piene è transitoria, e se il client ristrasmette il SYN è probabile che +passato un po' di tempo possa trovare lo spazio per una nuova connessione. Se +invece si rispondesse con un RST la \texttt{connect} del client ritornerebbe +con una condizione di errore, mentre questo è il tipico caso in cui è si può +lasciare la gestione della connessione alla ritrasmissione prevista dal +protocollo TCP. + + \subsection{La funzione \texttt{accept}} \label{sec:TCPel_func_accept} + +\begin{prototype}{sys/socket.h}{int listen(int sockfd, struct sockaddr *addr, + socklen_t *addrlen); } + + La funzione restituisce 0 in caso di successo e ... . I + codici di errore restituiti in \texttt{errno} sono i seguenti: + \begin{errlist} + \item \texttt{EBADF} L'argomento \texttt{sockfd} non è un file descriptor + valido. + \item \texttt{ENOTSOCK} L'argomento \texttt{sockfd} non è un socket. + \item \texttt{EOPNOTSUPP} Il socket è di un tipo che non supporta questa + operazione. + + \item \texttt{EAGAIN} or \item \texttt{EWOULDBLOCK} Il socket è stato + settato come non bloccante, e non ci sono connessioni in attesa di essere + accettate. + + \item \texttt{EFAULT} The addr parameter is not in a writable part of the + user address space. + + \item \texttt{EPERM} Firewall rules forbid connection. + + \item \texttt{ENOBUFS, ENOMEM} Not enough free memory. This often means + that the memory allocation is limited by the socket buffer limits, not by + the system memory. + \end{errlist} +\end{prototype} + \section{Una semplice implementazione del servizio \texttt{echo} su TCP} \label{sec:TCPel_echo_example} + + + + + +