Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

2 Processes listening on the same port - .NET not throwing exception

The image below shows 2 processes that attempted and successfully bound listen sockets (server) to port 10000 on my local machine:

Sysinternals showing 2 binds on port 10000

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:

  1. 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;
    
  2. .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.

  3. 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?

like image 562
MrCC Avatar asked Nov 13 '12 10:11

MrCC


People also ask

Can we use same port for 2 listeners?

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).

Can two processes share the same port?

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.

Can multiple processes use the same socket?

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.

Can multiple sockets bind to same port?

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.


2 Answers

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.

like image 89
Christopher Currens Avatar answered Oct 27 '22 23:10

Christopher Currens


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?

like image 28
Diego Avatar answered Oct 28 '22 00:10

Diego