Unusual ServerSocket Behaviour

T

Thomas Hawkins

Perhaps someone with a better understanding of TCP/IP will be able to
explain this. I have a small client-server application that works in
the following way:

An instance of a Runnable class called Server is created and started
as a thread. In this thread a ServerSocket is created, which blocks on
accept(). When the ServerSocket receives a connection, the resulting
Socket is handed to the constructor of another Runnable object called
ServerConnection. The ServerConnections starts itself as a thread and
handles the Socket from that point on. Once a new ServerConnection has
been created, the ServerSocket returns to blocking on accept(). The
lifetime of a ServerConnection is indefinite and can be terminated by
either the client or the server. Upon termination, the IO Streams and
Sockets are closed at both ends and the threads expire. The admin can
stop the Server by issuing a command that calls close() on the
ServerSocket. Once the closing Server thread has reported that it has
expired gracefully, the admin can restart the server by issuing a
command that creates a new instance of the Server thread. This all
appears to work as expected.

Now for the part I don't understand:

1. The Server is started: netstat indicates a socket LISTENING on the
designated port.

2. A connection is received: netstat indicates an additional socket on
that port in an ESTABLISHED state.

3. The Server is stopped: netstat indicates no change, but the
Server's final message states that the ServerSocket is now closed and
unbound.

4. A new Server is started: netstat indicates *another* socket
LISTENING on the same port. No BindException occurs. The new Server
reports that its ServerSocket is open, bound and listening.

5. At this point one of two things can happen. Either the new
ServerSocket will accept connections exactly as the first did, or
clients attempting to connect to the designated port will get a
"ConnectException: Connection refused", as if no server was there. The
connection that was spawned from the first ServerSocket continues to
work normally. If the second ServerSocket is not working, it will only
start working once this first connection is terminated. Terminating
the first connection causes the first ServerSocket to disappear from
netstat.

Can anyone explain what is going on here? It seems that the open
connection prevents the descriptor for the first ServerSocket from
disappearing from netstat, even though the ServerSocket no longer
exists as far as Java is concerned. So maybe the fact that clients
cannot connect to the new Server is due to their packets being routed
to the disappeared ServerSocket, even though there is another
ServerSocket that's actually bound to the port. The really perplexing
factor is the inconsistency of the behaviour.

I guess the obvious solution is to prevent the Server from shutting
down while there are still Sockets open. I can't think of another
server application that doesn't do this. For various reasons it would
be desirable in this case if one could restart the server without
closing existing connections. Is this impossible?

Any thoughts, theories or explanations would be appreciated.

Thanks

Tom
 
S

Steve Horsley

Thomas said:
Perhaps someone with a better understanding of TCP/IP will be able to
explain this. I have a small client-server application that works in
the following way:
<snip>

Hmm. Not what I would have expected - I guess I would expect the same as
yourself. I suspect this will prove to be behaviour as OS level that you
can't control (but only a guess).

What OS is this on?

If you want to refuse incoming connections for a while, you could just
accept and immediately close incoming calls until you're in a better
mood - no need to close the ServerSocket and try to re-create a new one.

Steve
 
T

Thomas Hawkins

Steve Horsley said:
<snip>

Hmm. Not what I would have expected - I guess I would expect the same as
yourself. I suspect this will prove to be behaviour as OS level that you
can't control (but only a guess).

What OS is this on?

If you want to refuse incoming connections for a while, you could just
accept and immediately close incoming calls until you're in a better
mood - no need to close the ServerSocket and try to re-create a new one.

Steve

Hi Steve,

Thanks for replying. This behaviour is on win98 SE. I haven't tried it
on Linux yet but that's a very good idea. I'll probably get flamed for
saying this but my favourite development environment for Java is
TextPad; and as I have always found Java's cross-platform performance
to be fairly good, I tend to work in windows.

I think it's plausible that this has something to do with the TCP/IP
implementation. The best theory I have so far is that when there are
two file descriptors registered as LISTENING on the same port, the OS
can get confused as to which one should receive new connections. If it
tries to route data to the ServerSocket that is closed it would
legitimately respond with a "could not connect". Also, if the second
ServerSocket gets lost in the way I describe, it stays lost; whereas
if it works, it keeps working. That might suggest that it has
something to do with how the OS searches for sockets registered to
listen on a given port. In other words, the implementation might
assume that there *should* only be one file descriptor registered as
LISTENING against a given port and routes data to which ever one it
finds first in a list somewhere. I don't know, something like that. I
confess I am just figuring this stuff out for the first time.

In the end I came to the same conclusion as you and am now refusing
connections within the application protocol. I'll post another reply
if I unearth different behaviour on Linux.

Thanks again,

Tom
 
S

Steve Horsley

Thomas said:
Hi Steve,

Thanks for replying. This behaviour is on win98 SE. I haven't tried it
on Linux yet but that's a very good idea. I'll probably get flamed for
saying this but my favourite development environment for Java is
TextPad; and as I have always found Java's cross-platform performance
to be fairly good, I tend to work in windows.
Not a flame, but a suggestion. Try BlueJ (www.bluej.org). It's my
favourite. Give it one day.

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top