The image below shows 2 processes that attempted and successfully bound listen sockets (server) to port 10000 on my local machine:
and here's the output of netstat (for confirmation):
netstat -a -n | find "10000"
TCP 0.0.0.0:10000 0.0.0.0:0 LISTENING
TCP 0.0.0.0:10000 0.0.0.0:0 LISTENING
TCP [::]:10000 [::]:0 LISTENING
(NB: The javaw.exe process was the first to open the listen socket on 10000).
While I am aware of situations under which multiple processes can indeed listen on the same port (SO_REUSEADDR
), there are certain things that bother me in my specific scenario:
In my application, I specifically say to .NET that I want an exclusive listen socket (SO_EXCLUSIVEADDRUSE
) via
listener = new TcpListener(adr, ipport);
listener.ExclusiveAddressUse = true;
.NET does not throw any kind of exception / error / notification that the port is already in use. In fact, it actually believes that everything went fine.
My server application never wakes up from the listener.AcceptTcpClient()
call from this point on. The client application that is supposed to communicate with the server receives a valid connection but is unable to communicate with "my" server (supposedly because it establishes a connection to the "other" process which doesn't speak its "protocol").
In case someone wants to try and reproduce my findings: The 2nd process is the "Helios" release of Eclipse (PHP). But the specific process shouldn't matter here: If one process can do weird things under an OS, so can others.
Any advice on how I can either get an error or prevent such a situation (by means of additional parameters) altogether?
It is possible. You just have to bind on the right IP address/interface each service using the same port. Ports (be them UDP or TCP) have their own pool per IP address. You can listen on the same port if you change: IP address or protocol (UDP or TCP).
You can make two applications listen for the same port on the same network interface. There can only be one listening socket for the specified network interface and port, but that socket can be shared between several applications.
Alternatively you can have multiple processes bound and listening on the same socket. If you fire up two processes each executing the above code it will work and the first process seems to get all the connections. If the first process is killed the second one then gets the connections.
When multiple sockets are allowed to bind to the same port, other services on that port may be stolen or spoofed. On most systems, a combination of setting the SO_REUSEADDR socket option, and a call to bind() allows any process to bind to a port to which a previous process has bound with INADDR_ANY.
The MSDN link you posted in your comment seems to answer your question.
It has to do with the java application binding to the wildcard IP endpoint (0.0.0.0
ip4; ::
for ip6, or IPEndpoint.ANY
). I'm assuming that the adr
variable in your code snippet above is a specific IP address, and not also a wildcard address.
Take a look at the tables in that article. It lists the outcomes of trying to bind to either a specific or wildcard endpoint a second time, with different combinations of socket options.
In short, the Java code is binding on the wildcard 0.0.0.0
endpoint without the SO_EXCLUSIVEADDRUSE
socket option. The matrix shows that when this happens, you can successfully bind to a specific address and pass requesting exclusive address use.
If you were to try and bind with a wildcard, the table shows that the call would fail.
Not sure why it's not throwing an exception. Although, the docs say TcpListener
's constructor doesn't really validate whether the port is open or not, and so, it only throws an ArgumentException
when the port number is invalid. Other methods, like Start
will throw a SocketException
with ErrorCode
set to WSAEADDRINUSE
(10048) when the port is already opened by another process (see Start method and Socket Error Codes).
To prevent this, either call Start
and catch the SocketException
or use the namespace System.Net.NetworkInformation
to query for all ports used and figure out if a particular port is available, as in this answer: In C#, how to check if a TCP port is available?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With