Ancora sulle opzioni dei socket
authorSimone Piccardi <piccardi@gnulinux.it>
Wed, 6 Dec 2017 22:41:24 +0000 (22:41 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Wed, 6 Dec 2017 22:41:24 +0000 (22:41 +0000)
fileadv.tex
prochand.tex
sockctrl.tex

index a3e8710..5cdcf42 100644 (file)
@@ -3860,6 +3860,7 @@ per il campo \var{aio\_sigevent} di \struct{aiocb}.
 % http://webfiveoh.com/content/guides/2012/aug/mon-13th/linux-asynchronous-io-and-libaio.html, 
 % https://code.google.com/p/kernel/wiki/AIOUserGuide,
 % http://bert-hubert.blogspot.de/2012/05/on-linux-asynchronous-file-io.html 
+% https://www.fsl.cs.sunysb.edu/~vass/linux-aio.txt
 
 
 \section{Altre modalità di I/O avanzato}
@@ -4686,6 +4687,10 @@ caching dei dati.
 \end{table}
 
 % TODO aggiunta MADV_FREE dal kernel 4.5 (vedi http://lwn.net/Articles/590991/)
+% TODO aggiunta MADV_WIPEONFORK dal kernel 4.14 that causes the affected memory
+% region to appear to be full of zeros in the child process after a fork. It
+% differs from the existing MADV_DONTFORK in that the address range will
+% remain valid in the child (dalla notizia in https://lwn.net/Articles/733256/).  
 
 \footnotetext{a partire dal kernel 2.6.32 è stato introdotto un meccanismo che
   identifica pagine di memoria identiche e le accorpa in una unica pagina
index 907a823..495851d 100644 (file)
@@ -4313,6 +4313,8 @@ elenco, che illustra quelle attualmente disponibili:\footnote{si fa
 %TODO trattare membarrier, introdotta con il kernel 4.3
 % vedi http://lwn.net/Articles/369567/ http://lwn.net/Articles/369640/
 % http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=5b25b13ab08f616efd566347d809b4ece54570d1 
+% vedi anche l'ulteriore opzione "expedited" introdotta con il kernel 4.14
+% (https://lwn.net/Articles/728795/) 
 
 \section{Problematiche di programmazione multitasking}
 \label{sec:proc_multi_prog}
index c074a44..a0512bf 100644 (file)
@@ -2207,6 +2207,8 @@ riportato un elenco di queste opzioni in tab.~\ref{tab:sock_opt_socklevel}.
     \hline
     \const{SO\_ACCEPTCONN}&$\bullet$&        &         &\texttt{int}& 
                           Indica se il socket è in ascolto.\\
+    \const{SO\_ATTACH\_FILTER}&     &$\bullet$&         &\texttt{sock\_fprog}& 
+                          Aggancia un filtro BPF al socket.\\
     \const{SO\_BINDTODEVICE}&$\bullet$&$\bullet$&         &\texttt{char *}& 
                           Lega il socket ad un dispositivo.\\
     \const{SO\_BROADCAST}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& 
@@ -2217,6 +2219,8 @@ riportato un elenco di queste opzioni in tab.~\ref{tab:sock_opt_socklevel}.
                           Attiva il ``\textit{busy poll}'' sul socket.\\
     \const{SO\_DEBUG}    &$\bullet$&$\bullet$&$\bullet$&\texttt{int}& 
                           Abilita il debugging sul socket.\\
+    \const{SO\_DETACH\_FILTER}&    &$\bullet$&$\bullet$&\texttt{int}& 
+                          Rimuove il filtro BPF agganciato al socket.\\
     \const{SO\_DOMAIN}   &$\bullet$&         &         &\texttt{int}& 
                           Legge il tipo di socket.\\
     \const{SO\_DONTROUTE}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& 
@@ -2227,6 +2231,8 @@ riportato un elenco di queste opzioni in tab.~\ref{tab:sock_opt_socklevel}.
                           Controlla l'attività della connessione.\\
     \const{SO\_LINGER}   &$\bullet$&$\bullet$&         &\texttt{linger}&
                           Indugia nella chiusura con dati da spedire.\\
+    \const{SO\_LOCK\_FILTER}&    &$\bullet$&$\bullet$&\texttt{int}& 
+                          Blocca il filtro BPF agganciato al socket.\\
     \const{SO\_MARK}     &$\bullet$&$\bullet$&         &\texttt{int}&
                           Imposta un ``\textit{firewall mark}'' sul socket.\\
     \const{SO\_OOBINLINE}&$\bullet$&$\bullet$&$\bullet$&\texttt{int}& 
@@ -2276,7 +2282,10 @@ riportato un elenco di queste opzioni in tab.~\ref{tab:sock_opt_socklevel}.
 % TODO aggiungere e documentare SO_ATTACH_BPF, introdotta con il kernel 3.19,
 % vedi http://lwn.net/Articles/625224/
 % TODO aggiungere e documentare SO_INCOMING_CPU, introdotta con il kernel 3.19,
-
+% TODO documentare SO_PEERGROUPS introdotta con il kernel 4.13, citata
+% in https://lwn.net/Articles/727385/
+% TODO documentare SO_ZEROCOPY, vedi https://lwn.net/Articles/726917/ (e il
+% resto pure) introdotta con il kernel 4.14
 
 La tabella elenca le costanti che identificano le singole opzioni da usare
 come valore per \param{optname}; le due colonne seguenti indicano per quali
@@ -2299,15 +2308,23 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
 \item[\constd{SO\_ACCEPTCONN}] questa opzione permette di rilevare se il socket
   su cui opera è stato posto in modalità di ricezione di eventuali connessioni
   con una chiamata a \func{listen}. L'opzione può essere usata soltanto con
-  \func{getsockopt} e utilizza per \param{optval} un intero in cui viene
-  restituito 1 se il socket è in ascolto e 0 altrimenti. 
+  \func{getsockopt} ed utilizza per \param{optval} un intero in cui viene
+  restituito 1 se il socket è in ascolto e 0 altrimenti.
 
 \item[\constd{SO\_ATTACH\_FILTER}] questa opzione permette di agganciare ad un
-  socket un filtro di pacchetti che consente di selezionare quali pacchetti,
-  fra tutti quelli ricevuti, verranno letti. Viene usato principalmente con i
-  socket di tipo \const{PF\_PACKET} con la libreria \texttt{libpcap} per
-  implementare programmi di cattura dei pacchetti, torneremo su questo in
-  sez.~\ref{sec:packet_socket}.
+  socket un filtro di selezione dei pacchetti con la stessa sintassi del BPF
+  (\textit{Berkley Packet Filter}) di BSD, che consente di selezionare, fra
+  tutti quelli ricevuti, verranno letti. Può essere usata solo con
+  \func{setsockopt} ed utilizza per \param{optval} un puntatore ad una
+  struttura \struct{sock\_fprog} (definita in
+  \headfile{linux/filter.h}). Questa opzione viene usata principalmente con i
+  socket di tipo \const{PF\_PACKET} (torneremo su questo in
+  sez.~\ref{sec:packet_socket}) dalla libreria \texttt{libpcap} per
+  implementare programmi di cattura dei pacchetti, e per questo tipo di
+  applicazione è opportuno usare sempre quest'ultima.\footnote{la trattazione
+    del BPF va al di là dell'argomento di questa sezione per la documentazione
+    si consulti il file \texttt{networking/filter.txt} nella documentazione
+    del kernel.}
 
 \item[\constd{SO\_BINDTODEVICE}] questa opzione permette di \textsl{legare} il
   socket ad una particolare interfaccia, in modo che esso possa ricevere ed
@@ -2381,11 +2398,13 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
     programma, \cmd{trpt}.}
 
 \item[\constd{SO\_DETACH\_FILTER}] consente di distaccare un filtro
-  precedentemente aggiunto ad un socket.
-
-% TODO documentare SO_ATTACH_FILTER e SO_DETACH_FILTER
-% riferimenti http://www.rcpt.to/lsfcc/lsf.html
-% Documentation/networking/filter.txt
+  precedentemente aggiunto ad un socket con l'opzione
+  \const{SO\_ATTACH\_FILTER}, in genere non viene usata direttamente in quanto
+  i filtri BPF vengono automaticamente rimossi alla chiusura del socket, il
+  suo utilizzo è pertanto limitato ai rari casi in cui si vuole rimuovere un
+  precedente filtro per inserirne uno diverso. Come \const{SO\_ATTACH\_FILTER}
+  può essere usato solo \func{setsockopt} e prende per \param{optval} un
+  intero usato come valore logico.
 
 \item[\constd{SO\_DOMAIN}] questa opzione, presente dal kernel 2.6.32, legge
   il ``\textsl{dominio}'' (la famiglia di indirizzi) del socket.
@@ -2425,6 +2444,15 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
   fig.~\ref{fig:sock_linger_struct}.  Maggiori dettagli sul suo funzionamento
   sono forniti in sez.~\ref{sec:sock_options_main}.
 
+\item[\constd{SO\_LOCK\_FILTER}] consente di bloccare un filtro
+  precedentemente aggiunto ad un socket con l'opzione
+  \const{SO\_ATTACH\_FILTER}, in modo che non possa essere né rimosso né
+  modificato, questo consente di impostare un filtro su un socket, bloccarlo e
+  poi cedere i privilegi con la sicurezza che il filtro permarrà fino alla
+  chiusura del socket. Come \const{SO\_ATTACH\_FILTER} può essere usato solo
+  \func{setsockopt} e prende per \param{optval} un intero usato come valore
+  logico.
+
 \item[\constd{SO\_MARK}] questa opzione, presente dal kernel 2.6.25, imposta
   un valore di marcatura sui pacchetti del socket. Questa è una funzionalità
   specifica di Linux, ottenibile anche con l'uso del target \texttt{MARK}
@@ -2575,31 +2603,11 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
   socket.  Maggiori dettagli sul suo funzionamento sono forniti in
   sez.~\ref{sec:sock_options_main}.
 
-
 \item[\const{SO\_REUSEPORT}] questa opzione, presente a partire dal kernel
   3.9, permette di far usare a più socket di tipo \const{AF\_INET} o
-  \const{AF\_INET6} lo stesso indirizzo locale. L'opzione deve essere attivata
-  sul socket prima di chiamare \func{bind} e richiede che tutti i processi che
-  si mettono in ascolto sullo stesso indirizzo abbiano lo stesso \ids{UID}
-  effettivo, per evitare che un altro utente possa ottenere il relativo
-  traffico (eseguendo quello che viene definito in \textit{port hijacking});
-  l'opzione utilizza per \param{optval} un intero usato come valore logico.
-
-  L'opzione si usa sia per socket TCP che UDP, nel primo caso consente un uso
-  distribuito si \func{accept} in una applicazione \textit{multithreaded}
-  passando un diverso \textit{listening socket} ad ogni thread (cosa che
-  migliora le prestazioni rispetto all'approccio tradizionale di usare un
-  thread per usare \func{accept} e distribuire le connessioni o avere più
-  thread che competono per usare \func{accept} sul socket. Nel caso di UDP
-  l'opzione consente di distribuire meglio i pacchetti su più processi o
-  thread rispetto all'approccio tradizionale di far competere gli stessi per
-  l'accesso in ricezione al socket.
-
-
-% TODO documentare SO_REUSEPORT introdotta con il kernel 3.9, vedi
-% http://git.kernel.org/linus/c617f398edd4db2b8567a28e899a88f8f574798d 
-% TODO: in cosa differisce da REUSEADDR?
-
+  \const{AF\_INET6} lo stesso indirizzo locale, e costituisce una estensione
+  della precedente \const{SO\_REUSEADDR}.  Maggiori dettagli sul suo
+  funzionamento sono forniti in sez.~\ref{sec:sock_options_main}.
 
 \item[\constd{SO\_RXQ\_OVFL}] questa opzione, presente dal kernel 2.6.33,
   permette di abilitare o disabilitare sul socket la ricezione di un messaggio
@@ -2662,30 +2670,6 @@ tab.~\ref{tab:sock_opt_socklevel} sul significato delle varie opzioni:
   \param{optval} un intero in cui verrà restituito il valore numerico che lo
   identifica (ad esempio \const{SOCK\_STREAM}). 
 
-\item[\constd{SO\_DETACH\_FILTER}] consente di distaccare un filtro
-  precedentemente aggiunto ad un socket.
-
-% TODO documentare SO_ATTACH_FILTER e SO_DETACH_FILTER
-% riferimenti http://www.rcpt.to/lsfcc/lsf.html
-% Documentation/networking/filter.txt
-
-% TODO documentare SO_MARK, introdotta nel 2.6.25, richiede CAP_NET_ADMIN
-%A userspace program may wish to set the mark for each packets its send
-%without using the netfilter MARK target. Changing the mark can be used
-%for mark based routing without netfilter or for packet filtering.
-
-
-% TODO documentare SO_TIMESTAMP e le altre opzioni di timestamping dei 
-% pacchetti, introdotte nel 2.6.30, vedi nei sorgenti del kernel:
-% Documentation/networking/timestamping.txt
-
-
-% TOFO documentare SO_REUSEPORT introdotta con il kernel 3.9, vedi
-% http://git.kernel.org/linus/c617f398edd4db2b8567a28e899a88f8f574798d 
-
-% TODO documentare SO_PEERGROUPS introdotta con il kernel 4.13, citata
-% in https://lwn.net/Articles/727385/
-
 
 \end{basedescript}
 
@@ -2808,9 +2792,9 @@ attivando il relativo comportamento.
 
 
 \constbeg{SO\_REUSEADDR}
-\subsubsection{L'opzione \const{SO\_REUSEADDR}}
+\subsubsection{Le opzioni \const{SO\_REUSEADDR} e \const{SO\_REUSEADDR}}
 
-La seconda opzione da approfondire è \const{SO\_REUSEADDR}, che consente di
+La seconda opzione da approfondire è \constd{SO\_REUSEADDR}, che consente di
 eseguire \func{bind} su un socket anche quando la porta specificata è già in
 uso da parte di un altro socket. Si ricordi infatti che, come accennato in
 sez.~\ref{sec:TCP_func_bind}, normalmente la funzione \func{bind} fallisce con
@@ -2832,13 +2816,13 @@ figli che mantengono attiva almeno una connessione remota che utilizza
 l'indirizzo locale, mantenendo occupata la porta. Quando si riesegue il server
 allora questo riceve un errore sulla chiamata a \func{bind} dato che la porta
 è ancora utilizzata in una connessione esistente.\footnote{questa è una delle
-  domande più frequenti sui newsgroup dedicati allo sviluppo, in quanto è
-  piuttosto comune trovarsi in questa situazione quando si sta sviluppando un
-  server che si ferma e si riavvia in continuazione dopo aver fatto
-  modifiche.}  Inoltre se si usa il protocollo TCP questo può avvenire anche
-dopo tutti i processi figli sono terminati, dato che una connessione può
-restare attiva anche dopo la chiusura del socket, mantenendosi nello stato
-\texttt{TIME\_WAIT} (vedi sez.~\ref{sec:TCP_time_wait}).
+  domande più frequenti relative allo sviluppo, in quanto è piuttosto comune
+  trovarsi in questa situazione quando si sta sviluppando un server che si
+  ferma e si riavvia in continuazione dopo aver fatto modifiche.}  Inoltre se
+si usa il protocollo TCP questo può avvenire anche dopo tutti i processi figli
+sono terminati, dato che una connessione può restare attiva anche dopo la
+chiusura del socket, mantenendosi nello stato \texttt{TIME\_WAIT} (vedi
+sez.~\ref{sec:TCP_time_wait}).
 
 Usando \const{SO\_REUSEADDR} fra la chiamata a \func{socket} e quella a
 \func{bind} si consente a quest'ultima di avere comunque successo anche se la
@@ -2863,7 +2847,6 @@ finire fra quelli di una nuova.
   \label{fig:sockbindopt_code}
 \end{figure}
 
-
 Come esempio di uso di questa connessione abbiamo predisposto una nuova
 versione della funzione \texttt{sockbind} (vedi fig.~\ref{fig:sockbind_code})
 che consenta l'impostazione di questa opzione. La nuova funzione è
@@ -2920,10 +2903,12 @@ impostato \const{SO\_REUSEADDR}.
 Usando questa opzione diventa anche possibile eseguire \func{bind}
 sull'indirizzo generico, e questo permetterà il collegamento per tutti gli
 indirizzi (di quelli presenti) per i quali la porta non risulti occupata da
-una precedente chiamata più specifica. Infine si tenga presente che con il
-protocollo TCP non è in genere possibile far partire server che eseguano
-\func{bind} sullo stesso indirizzo e la stessa porta, cioè ottenere quello che
-viene chiamato un \textit{completely duplicate binding}.
+una precedente chiamata più specifica. Si tenga presente infatti che con il
+protocollo TCP non è in genere possibile far partire più server che eseguano
+\func{bind} sullo stesso indirizzo e la stessa porta se su di esso c'è già un
+socket in ascolto, cioè ottenere quello che viene chiamato un
+\itindex{completely~duplicate~binding} \textit{completely duplicate binding}
+(per questo è stata introdotta \const{SO\_REUSEPORT}).
 
 Il terzo impiego è simile al precedente e prevede l'uso di \func{bind}
 all'interno dello stesso programma per associare indirizzi locali diversi a
@@ -2940,12 +2925,12 @@ invocare \func{getsockname} una volta che si è completata la connessione.
 Infine il quarto caso è quello in cui si vuole effettivamente ottenere un
 \textit{completely duplicate binding}, quando cioè si vuole eseguire
 \func{bind} su un indirizzo ed una porta che sono già \textsl{legati} ad un
-altro socket.  Questo ovviamente non ha senso per il normale traffico di rete,
-in cui i pacchetti vengono scambiati direttamente fra due applicazioni; ma
-quando un sistema supporta il traffico in \textit{multicast}, allora ha senso
-che su una macchina i pacchetti provenienti dal traffico in \textit{multicast}
-possano essere ricevuti da più applicazioni o da diverse istanze della stessa
-applicazione.
+altro socket.  Come detto normalmente questo non è possibile con TCP, e non ha
+senso per il traffico di rete in cui i pacchetti vengono scambiati
+direttamente fra due applicazioni; ma quando un sistema supporta il traffico
+in \textit{multicast}, allora ha senso che su una macchina i pacchetti
+provenienti dal traffico in \textit{multicast} possano essere ricevuti da più
+applicazioni o da diverse istanze della stessa applicazione.
 
 L'esempio classico di traffico in \textit{multicast} è quello di uno streaming
 di dati (audio, video, ecc.), l'uso del \textit{multicast} consente in tal
@@ -2956,36 +2941,65 @@ possano lanciare un programma che permetta loro di ricevere gli stessi dati.
 
 In questo caso utilizzando \const{SO\_REUSEADDR} si consente ad una
 applicazione eseguire \func{bind} sulla stessa porta ed indirizzo usata da
-un'altra, così che anche essa possa ricevere gli stessi pacchetti (chiaramente
-la cosa non ha alcun senso per i socket TCP, ed infatti in questo tipo di
-applicazione è normale l'uso del protocollo UDP). La regola è che quando si
-hanno più applicazioni che hanno eseguito \func{bind} sulla stessa porta, di
-tutti pacchetti destinati ad un indirizzo di \textit{broadcast} o di
-\textit{multicast} viene inviata una copia a ciascuna applicazione.  Non è
+un'altra, così che anche essa possa ricevere gli stessi pacchetti; come detto
+la cosa non è possibile con i socket TCP, ma lo è per quelli UDP che è il
+protocollo normalmente in uso da parte di queste applicazioni. La regola è che
+quando si hanno più applicazioni che hanno eseguito \func{bind} sulla stessa
+porta, di tutti pacchetti destinati ad un indirizzo di \textit{broadcast} o di
+\textit{multicast} viene inviata una copia a ciascuna applicazione. Non è
 definito invece cosa accade qualora il pacchetto sia destinato ad un indirizzo
 normale (\textit{unicast}).
 
 % TODO documentare SO_REUSEPORT, vedi https://lwn.net/Articles/542260/
 
-Essendo questo un caso particolare in alcuni sistemi (come BSD) è stata
-introdotta una opzione ulteriore, \const{SO\_REUSEPORT} che richiede che detta
-opzione sia specificata per tutti i socket per i quali si vuole eseguire il
-\textit{completely duplicate binding}. Nel caso di Linux questa opzione non
-esisteva fino al kernel 3.9, ma il comportamento di \const{SO\_REUSEADDR} è
-analogo, sarà cioè possibile effettuare un \textit{completely duplicate
-  binding} ed ottenere il successo di \func{bind} su un socket legato allo
-stesso indirizzo e porta solo se il programma che ha eseguito per primo
-\func{bind} su di essi ha impostato questa opzione. 
-
-Questa restrizione permette di evitare parzialmente il cosiddetto \textit{port
-  stealing}, in cui un programma, usando \const{SO\_REUSEADDR}, può collegarsi
-ad una porta già in uso e ricevere i pacchetti destinati ad un altro
-programma; con questa caratteristica ciò è possibile soltanto se il primo
-programma a consentirlo, avendo usato fin dall'inizio
-\const{SO\_REUSEADDR}. Con l'introduzione di \const{SO\_REUSEPORT} una
-ulteriore protezione deriva dalla richiesta che tutti i processi che usano
-questa opzione per un socket abbiano lo stesso \ids{UID} effettivo.
+\constbeg{SO\_REUSEPORT}
+
+Esistono però dei casi, in particolare per l'uso di programmi
+\textit{multithreaded}, in cui può essere necessario un \textit{completely
+  duplicate binding} 
+
+L'opzione deve essere attivata sul socket prima di chiamare \func{bind} e
+richiede che tutti i processi che si mettono in ascolto sullo stesso indirizzo
+abbiano lo stesso \ids{UID} effettivo, per evitare che un altro utente possa
+ottenere il relativo traffico (eseguendo quello che viene definito in
+\textit{port hijacking}); l'opzione utilizza per \param{optval} un intero
+usato come valore logico.
+
+  L'opzione si usa sia per socket TCP che UDP, nel primo caso consente un uso
+  distribuito si \func{accept} in una applicazione \textit{multithreaded}
+  passando un diverso \textit{listening socket} ad ogni thread (cosa che
+  migliora le prestazioni rispetto all'approccio tradizionale di usare un
+  thread per usare \func{accept} e distribuire le connessioni o avere più
+  thread che competono per usare \func{accept} sul socket. Nel caso di UDP
+  l'opzione consente di distribuire meglio i pacchetti su più processi o
+  thread rispetto all'approccio tradizionale di far competere gli stessi per
+  l'accesso in ricezione al socket.
 
+  % TODO documentare SO_REUSEPORT introdotta con il kernel 3.9, vedi
+  % http://git.kernel.org/linus/c617f398edd4db2b8567a28e899a88f8f574798d TODO:
+  % in cosa differisce da REUSEADDR?
+
+
+  Essendo questo un caso particolare in alcuni sistemi (come BSD) è stata
+  introdotta una opzione ulteriore, \const{SO\_REUSEPORT} che richiede che
+  detta opzione sia specificata per tutti i socket per i quali si vuole
+  eseguire il \textit{completely duplicate binding}. Nel caso di Linux questa
+  opzione non esisteva fino al kernel 3.9, ma il comportamento di
+  \const{SO\_REUSEADDR} è analogo, sarà cioè possibile effettuare un
+  \textit{completely duplicate binding} ed ottenere il successo di \func{bind}
+  su un socket legato allo stesso indirizzo e porta solo se il programma che
+  ha eseguito per primo \func{bind} su di essi ha impostato questa opzione.
+
+  Questa restrizione permette di evitare parzialmente il cosiddetto
+  \textit{port stealing}, in cui un programma, usando \const{SO\_REUSEADDR},
+  può collegarsi ad una porta già in uso e ricevere i pacchetti destinati ad
+  un altro programma; con questa caratteristica ciò è possibile soltanto se il
+  primo programma a consentirlo, avendo usato fin dall'inizio
+  \const{SO\_REUSEADDR}. Con l'introduzione di \const{SO\_REUSEPORT} una
+  ulteriore protezione deriva dalla richiesta che tutti i processi che usano
+  questa opzione per un socket abbiano lo stesso \ids{UID} effettivo.
+
+\constend{SO\_REUSEPORT}
 \constend{SO\_REUSEADDR}