Gidday,
In the classical BSD sockets implementation, the
SO_REUSEADDR socket option serves two purposes:
(a) to permit a socket to be bound to a port that currently
has a bound endpoint in the TIME_WAIT state, and
(b) to allow a terminated server to be restarted (and once
again be bound to it's well-known port), even if there
is a child of the previous server still serving a
connection.
On Linux SO_REUSEADDR does serve this purpose. However,
other second scenario is mot permitted by SO_REUSEADDR.
To make it clear what I mean, I?ll detail the scenario.
Suppose we have the following:
Server (host Y)
Create listening socket -- fd 4
bind() to INADDR_ANY:9999
listen()
accept()
Client (host X)
Create socket
connect() to Y:9999 <accept unblocks, fd 5 returned>
server forks --------+
\ <child>
server terminates closes fd 4
<keeps running, with
fd 5 holding the
connection to client>
At this point, netstat on host Y shows the tuple
[local=Y-IP-addr:9999, remote=X-IP-addr:ephem-port] ESTABLISHED
New Server started
Create listening socket -- fd 4
set SO_REUSEADDR to 1 for fd 4
bind() fd 4 to port INADDR_ANY:9999
WHAT HAPPENS?
On FreeBSD, the bind() succeeds, and then using "netstat ?an"
on host Y shows:
[local=Y-IP-addr:9999, remote=X-IP-addr:ephem-port] ESTABLISHED
and
[local=*:9999, remote=*.*] CLOSED
But on Linux (2.6), the bind() fails with EADDRINUSE.
Why does Linux behave differently in this scenario?
Cheers,
Michael
--
Michael Kerrisk
mtk-lists@xxxxxxx
NEU: WLAN-Router für 0,- EUR* - auch für DSL-Wechsler!
GMX DSL = supergünstig & kabellos http://www.gmx.net/de/go/dsl
|