Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 16 Sep 2001 14:59:24 -0700
From:      Terry Lambert <tlambert2@mindspring.com>
To:        Stephen Montgomery-Smith <stephen@math.missouri.edu>
Cc:        freebsd-hackers@FreeBSD.ORG
Subject:   Re: Could not bind
Message-ID:  <3BA520BC.E26A64F0@mindspring.com>
References:  <3BA3F70D.27C2136@math.missouri.edu>

next in thread | previous in thread | raw e-mail | index | archive | help
Stephen Montgomery-Smith wrote:
> 
> I have written a server program that listens on port 3000.  The program
> works very well except for one feature.  I am asking if that is normal,
> or whether I forgot something.
> 
> If I run the program it does fine.  If I then kill the program (after it
> has accepted connections), and then run the program again, the bind
> function fails to work, and I get a message like "Could not bind" (see
> program below).  If I wait a while, like a minute or two, then the
> program will work again. Is this normal behavior, or did I miss
> something?

This is normal.

When a server closes the connection, which will occur in the
resource-track-cleanup case of you killing the server, the
connections effectively undergo a "host close".  If the clients
are still around and responsive, these conections will go away
quickly.  If not, then these connections will hand around a
long time.  In addition, in the case of client initiated closes
prior to your temination of the program, the sockets will be in
TIME_WAIT state for 2MSL -- 60 seconds, by default.

So in normal operation, you should expect that you will not be
able to restart the server for at least 60 seconds, and perhaps
more, unless you have unset the "keepalive" socket option on the
sockets to prevent the FIN_WAIT_2 state.

A common overreaction to improrper state tracking by the programmer,
or improper "clean shutdown" of a server is to set SO_REUSEADDR
on the listen socket of the server.  THis lets you restart the
server.  But it also lets you start multiple instances of the
server, so if you are doing things like cookie state tracking which
are server instance specific (e.g. for an HTTP server), then you
have shot yourself in the foot, unless this state is shared between
all server instances, and your servers are anonymous work-to-do
engines, rather than being specific-purpose (this is because you
can not control the connections to make them go to one server vs.
another, if both are listening on the same port).

Ideally, you would correct the shutdown so that it was clean,
and correct the socket options, if what you are intending is
to abort the server without sending complete data to the client
(e.g. unsetting SO_LINGER will cause the sending of an RST on
close, avoiding the TIME_WAIT, but potentially leaving the
client hanging until the longer -- 2 hour, by default -- clock
on the client sends a keepalive, and the RST is resent; this is
because RST's are not resent, as they do not get acknowledgement).

As a workaround, you can set SO_REUSEADDR on the socket.  Above,
I labelled this as an overreaction... it is.  For this to work,
you will probably need to make sure your server creates a pid
file in /var/run/<servername>.pid, and then, before you reopen
the socket, verify via kill(2), using a <signal> argument of 0,
that the process is in fact dead, before grabbing its port out
from under it for half the inbound connections (see the "2 kill"
man page for details on the 0 signal; a 0 return or a -1 return
with errno == EPERM mean the process your are trying to replace
is already running).


> I got the programming style from Richard Steven's book on network
> programming.  The structure of the program is something like this:

[ ... example elided ... ]

That's all fine; the problem is just an incomplete understanding
of the TCP protocol; hopefully the above will fill you in; in the
man time, you may want to get the internals volumes from the
Steven's books series, and read them, as well, since it's often
useful to understand why you are seeing what you are seeing; the
user space volumes are only half the story.

-- Terry

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3BA520BC.E26A64F0>