Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
SO_REUSEADDR socket option
01-11-2013, 09:38 PM
Post: #1
SO_REUSEADDR socket option
The ohNet device stack uses the SO_REUSEADDR socket option when binding its TCP listener socket. If an application sets a fixed port number using the SetDvUpnpServerPort API call, this causes strange behaviour when two instances of this application are started in separate processes on the same machine:

1) The first instance is started, and is visible to control points via the fixed port

2) The second instance is started. No error is reported, and its listener socket is bound to the same IP address and port as the first instance. This makes the second instance invisible to control points, because control point messages sent to the fixed port in response to device advertisements from the second instance will be received by the first instance instead of the second instance.

I have verified the above behaviour on Windows. As the SO_REUSEADDR socket option is also set for Linux, I would expect similar behaviour, but I haven't verified this.

The problem (from the user's perspective) is that his/her configuration error of using the same fixed port for two different instances has caused the second instance to be nonfunctional, but it appears to start normally without reporting an error.

Is this behaviour intentional? If so, what is the valid scenario that requires the use of SO_REUSEADDR to enable multiple ohNet application processes on the same machine to bind to the same combination of IP address and port?
Find all posts by this user
02-11-2013, 11:40 AM
Post: #2
RE: SO_REUSEADDR socket option
I might have some of the details wrong but the general behaviour should be roughly correct...

TCP sockets enter a TIME_WAIT state after being closed; this allows for any in-flight messages to be detected as being intended for a closed socket, allowing the network stack to discard them. Without this, there is a risk of a new socket receiving a message intended for the previous user of that address/port. The downside of this is that you can't then stop then quickly restart an application which uses fixed ports. SO_REUSEADDR provides an option to get round this, allowing a socket to bind to an address/port that is still in TIME_WAIT state.

So far behaviour across platforms is fairly consistent. It now starts to diverge... If an existing socket is bound to an address/port, Linux will fail a second attempt to bind, regardless of whether SO_REUSEADDR is set. I'd expect this to mean that attempting to start a second instance of MinimServer on Linux would fail.

Windows behaves differently, forcibly binding the second socket and now sending any messages for that address/port to the second socket, ignoring the previous and still active socket. As you've noticed, this allows two app instances to start on Windows.

Removing use of SO_REUSEADDR would fix your Windows problem but would introduce others for any code that quickly restarts. At a minimum, this would be quite disruptive for test code. I think it'd also be a big problem for any apps which include a monitor process which automatically restart the app following any crash. It might be easier to deal with this in application code. Each app instance could try to create a globally visible object; a second instance would fail to create this object and could then exit. Just in case there aren't any suitable Java objects to help with this, a plain Win32 Semaphore should be an option.
Find all posts by this user
10-12-2013, 12:05 PM (This post was last modified: 22-01-2016 06:08 AM by henn9438.)
Post: #3
RE: SO_REUSEADDR socket option
Thanks for the documentation and advice. Its really helpful

Find all posts by this user

Forum Jump: