[erlang-questions] Multicast UDP sending question

Valentin Micic <>
Fri Nov 20 18:15:25 CET 2009


Sam,

SO_REUSADDR is a very *old* option with a definite semantics (and behavior)
when it comes to TCP:

1) Servers are reusing the same local port (as in listeners) because clients
are using different IP address and port.

2) Clients may reuse the same port (as in FTP client, for example) because
servers utilizes different port (e.g. port 20 for commands and port 21 for
transfer -- or was it the other way around).

3) Some other listener/connections may be started because connection enters
TIME_WAIT state.

This is possible because any association is presented using 5 elements:

{Protocol, LocalIP, LocalPort, RemoteIP, RemotePort}.

So it is easy to see that TCP may support local process reuse if and only if
the remote half of the connection makes the association unique. In other
words:

{tcp, "127.0.0.1", 5001, "127.0.0.1", 20}
{tcp, "127.0.0.1", 5001, "127.0.0.1", 21}

Situation with UDP is not clear as there is no connection, hence no known
remote half of the association to make it unique. 

Your test indicates -- even though you've managed to bind two different
processes (e.g. Erlang runtimes) to the same UDP port; the behavior is
unpredictable from the process' point of view. In other words, the process
may receive traffic under some circumstances (say, started first), and not
under another (e.g. started second, but may receive traffic if first process
terminates).

It would be interesting to test two Erlang runtimes (or any two independent
processes) attempting to use the same TCP port as listeners specifying
SO_REUSEADDR on both sockets. This situation would closely resemble UDP
situation as it does not have remote half of the association, but only local
resources:

{tcp, LocalIp, LocalPort}.

I remember that I've tested this once and it didn't work on any of the
available unices: SunOS, HP/UX, DG/UX (don't remember if I tested it on
SCO).


V/

-----Original Message-----
From: Sam Bobroff [mailto:] 
Sent: 20 November 2009 06:21 PM
To: Valentin Micic
Cc: 'Jarrod Roberson'; 'Torben Hoffmann'; 'Erlang'
Subject: Re: [erlang-questions] Multicast UDP sending question

Valentin Micic wrote:
> Don't know what to tell you -- I've tried similar thing from Windoze and
got
> what I've expected:
>
> Started two shells with following result:
>
> FIRST:
>
> Erlang (BEAM) emulator version 5.5.4 [async-threads:0]
>
> Eshell V5.5.4  (abort with ^G)
> ()1> gen_udp:open( 9999, [{reuseaddr, true}] ).
> {ok,#Port<0.97>}
> ()2>
>
> SECOND:
>
> Erlang (BEAM) emulator version 5.5.4 [async-threads:0]
>
> Eshell V5.5.4  (abort with ^G)
> ()1> gen_udp:open( 9999, [{reuseaddr, true}] ).
> {error,eaddrinuse}
> ()2>
>
>
> Hope this is helpful too.
>
> V/
That IS quite interesting! I found some documentation on MSDN that 
seemed to indicate that SO_REUSEADDR was available under Windows, and 
that it actually did pretty much the same thing as Linux... So if that 
were the case then Erlang must be doing something differently. I grepped 
around in the source code and look what I found in "inet_setopts" in 
"inet_drv.c":

    case INET_OPT_REUSEADDR:
#ifdef __WIN32__
        continue;  /* Bjorn says */
#else
        type = SO_REUSEADDR;
        DEBUGF(("inet_set_opts(%ld): s=%d, SO_REUSEADDR=%d\r\n",
            (long)desc->port, desc->s,ival));
        break;
#endif

(From R13B02)

So! reuseaddr does *nothing* in Erlang under Windows, but on other OSes 
it does! That certainly explains our different results. Perhaps the 
Erlang documentation for gen_udp should mention that this flag is 
unimplemented on Windows?

Sam.



More information about the erlang-questions mailing list