Normally only one process can listen on a TCP port, on Windows or any other OS (at least the major ones). On Windows you'd expect to get error code 10048 if two processes share the port. This won't apply if the processes are bound to different interface addresses (even if one is bound to INADDR_ANY
and the other is bound to a specific address, they don't clash). Also, this doesn't apply if SO_REUSEADDR
has been set on the second socket.
Since both processes are bound to INADDR_ANY
and you claim your process hasn't had SO_REUSEADDR
set, however, this is a puzzle. As far as I can tell there are three possibilities:
- Something in the underlying library is setting
SO_REUSEADDR
by default.
- The second socket was actually opened later and it's the one specifying
SO_REUSEADDR
.
- There is a bug in the Windows sockets layer which allowed this.
I realise no software is perfect, but I really hesitate to choose the third option, especially if you can easily reproduce it. I would suggest carefully watching netstat
output before and after starting your process and seeing whether the other listener exists prior to that. Also, try to identify the other process and see whether it's related (you can enable the PID column in the task manager for that).
EDIT
The commenter below has reminded me that I should point out that the behaviour of SO_REUSEADDR
does differ across platforms. Windows allows new sockets using the option to forcibly bind to the same port as other listening sockets, with undetermined behaviour if the two sockets are both TCP, as discussed here. In practice the second socket probably "steals" the address, but the official line seems to be that the behaviour is undefined:
Once the second socket has successfully bound, the behavior for all sockets bound to that port is indeterminate. For example, if all of the sockets on the same port provide TCP service, any incoming TCP connection requests over the port cannot be guaranteed to be handled by the correct socket — the behavior is non-deterministic.
Linux (and other Unix variants) will not allow two TCP sockets to share the same port if the old one is still listening. In this case, SO_REUSEADDR
only allows the new socket to bind if the old one is in TIME_WAIT (and perhaps the FIN_WAIT and CLOSE_WAIT states, I'd have to check that).
As an aside, I found the difference in behaviour quite surprising when I first came across it in Windows, but I've tested it myself and certainly if you set SO_REUSEADDR
on both sockets it's quite possibly to bind successfully to exactly the same address and port simultaneously. I haven't done extensive testing on the exact behaviour in this situation, however, since in my case it didn't matter too much.
I'm not about to get into which platform is "correct", but certainly the Windows behaviour has lead to security issues which is why they came up with the SO_EXCLUSIVEADDRUSE
option to prevent other sockets forcibly binding. I've also seem people of the opinion that the Windows version should be regarded as a completely different option, with different behaviour, which just happens to have the same name.
setReuseAddress
? – FellersSO_REUSEADDR
so this behaviour is still puzzling since the OP claims not to have specified that option. See my answer for more details. – Rigel