eaddrinuse

Serge Aleynikov serge@REDACTED
Thu Apr 28 15:37:56 CEST 2005


Brian Buchanan wrote:
> On Thu, 28 Apr 2005, Dietmar Schaefer wrote:
>>If I understand it right
>>
>> {reuseaddr, Boolean} as parameter for  gen_tcp:listen  allows local
>>reuse of port numbers.
>>
>>
>>So the error eaddrinuse should not occur ?
>>
>>
>>Every time I try to reconnect to the server I get this error.
 >
 > reuseaddr (or SO_REUSEADDR as it is translated to the kernel) only allows
 > reuse of port numbers that were recently used but not currently in use.
 > (They are not normally available for some period of time in order to
 > provide a strict implementation of the TCP specification).  If another
 > open socket has that port number, you won't be able to bind it.

It looks like when you restart the server, the listener's Pid doesn't 
get terminated, and it's still holding the socket open.

Most common use of {reuseaddr, true} option is to handle reacquisition 
of a socket by a server in the following scenario:

1. A listening server is started.
2. It receives a connection request, and spawns a child process to 
handle it.
3. The listening server terminates without killing the child, who's 
still processing the request on the established connection.
4. The listening server gets restarted.

However, if you are trying to start the second instance of a TCP server 
and attempt to bind to the same IP:Port, it will fail even though 
{reuseaddr, true} is specified.

> I know that at least BSD-derived OSes support a SO_REUSEPORT option for
> setsockopt() that enables multiple sockets to simultaneously listen on the
> same address and port if all of them enable the option.  The Erlang inet
> module doesn't appear to support this flag, however.

I believe the duplicate bindings (i.e. to the same IP address and port) 
are *only* possible for UDP multicast binds.  TCP doesn't support this 
and should always fail with eaddrinuse if another process is active and 
is bound to that socket.  UDP non-multicast binds with {reuseaddr, true} 
will allow you to "steal" a socket from another process (without that 
process knowing about it), yet the kernel will only deliver UDP messages 
to the latest process that bound the UDP socket.

It is possible, however, to do a TCP bind to the same port if you use 
{reuseaddr, true}, and a *different* local IP address.

Serge



More information about the erlang-questions mailing list