On 4/5/07, Trustin Lee <[EMAIL PROTECTED]> wrote:
Hi Vinod and Coding horse,

On 4/5/07, Vinod Panicker <[EMAIL PROTECTED]> wrote:
<snip/>
> > I tried the following solutions:
> >
> > 1) acceptor.setReuseAddress(true);  ->  doesn't work.
> > 2) acceptor.getSessionConfig().setReuseAddress(true);  ->  works!
> >
> > It seems like Linux doesn't clean up connection state and prevents
> > binding the port which the dangling connection is referencing.  It
> > seems like setting a SO_REUSE_ADDR on an accepted socket disables the
> > protection.  I'm not sure how this differs in Windows.
>
> Cool.  It's interesting how its working when you set the option on the
> SessionConfig.  Technically speaking, an application is not supposed
> to bind again on a socket/port that is in a *_WAIT state, since the
> state exists so data "in transmission" may be safely expired.
> Rebinding a server on a socket in a wait state using the SO_REUSE_ADDR
> may be necessary for server systems (to reduce downtime), but could
> also potentially generate some interesting issues.
>
> The way it works is exactly the same on both Linux and Windows, and
> it's not a Linux issue, but rather the way the JVM is setting the
> SO_REUSE_ADDR option on the socket. I've coded servers in C++ on Linux
> and successfully managed to use this option for rebinding.
>
> Let me try your workaround - will get back on if it works for me too.

I found why. :D

Take a look at here:

SocketSessionConfigImpl: http://tinyurl.com/3468gf

DEFAULT_REUSE_ADDRESS is set to 'false' in Linux.  But, according to
the bug reporters, this problem didn't show up in non-MINA NIO
servers.  So I printed the REUSE_ADDR option as soon as a new
connection is accepted.  Guess what?  The default value of REUSE_ADDR
option for an accepted socket was 'true'!  This means that the default
values of socket options are different between a client socket and an
accepted socket. (and also probably true for a server socket?)

Therefore, we can conclude that all option parameters have to be
calculated for three kinds of sockets to fix this problem.

I quickly checked the default option values, and the following is the
list of differences I've found.

* reuseAddr is true for an accepted socket, while others return false.
* new Socket().getSendBufferSize() returns 8192, but new
Socket("localhost", avaialblePort).getSendBufferSize() and
acceptedSocket.getSendBufferSize() returns 25290.  It seems like we
need to create a connected socket by opening a port to get the correct
value.

Considering the differences above, I think we don't need to get all
option values for all kinds of sockets, and we can fix the buffer size
difference very easily.  Setting the default reuseAddr value in MINA
1.x will also be a piece of cake because we can simply change the
reuseAddr property after a SocketSessionImpl is created.

The tough part is setting the default reuseAddr value in MINA 2.0.  In
MINA 2.0, a user can call setSessionConfig(IoSessionConfig) with a new
DefaultSocketSessionConfig instance.  It is especially useful when
Springframework is used to configure the acceptor.  But, when a user
creates a new DefaultSocketSessionConfig instance, the instance itself
can't tell if it will be used for acceptor or connector.  The default
reuseAddr property can't be set correctly at least for one side.

There are three possible solutions:

* Remove setSessionConfig()
* Add a constructor parameter so user can choose
* Provide two classes; ConnectorSocketSessionConfig and
AcceptorSocketSessionConfig

I think the first one is the best for user friendliness if we can
provide proper spring integration.  Any idea on spring integration?
Or, you could tell us what the best solution is.

Trustin
--
what we call human nature is actually human habit
--
http://gleamynode.net/
--
PGP Key ID: 0x0255ECA6

Reply via email to