ispiro
ispiro

Reputation: 27693

Get auto-asigned local IP address of TcpListener

Here's my code:

TcpListener listener = new TcpListener(IPAddress.Any, 0);
listener.Start();
var v = (IPEndPoint)listener.LocalEndpoint;

According to the documentation

If you do not care which local address is assigned, specify IPAddress.Any for the localaddr parameter, and the underlying service provider will assign the most appropriate network address. ...If you use this approach, you can discover what local network address and port number has been assigned by using the LocalEndpoint property.

unfortunately, the address is always 0.0.0.0.

How do I discover the actual local ip address of the TcpListener?

EDIT

The code does work for the port. v does indeed have a specific port assigned to it.

Upvotes: 0

Views: 961

Answers (2)

Ben Voigt
Ben Voigt

Reputation: 283713

In additional to everything which Andy said about LocalEndpoint having the local address for each incoming connection, which is correct, this statement in the documentation is flat out wrong:

the underlying service provider will assign the most appropriate network address

Actually, LocalEndpoint will give you the address which the client sent the TCP SYN packet to. It will be one of your network addresses, and it will often be the one that the local routing table would choose if initiating a connection to that client address without first binding the outgoing socket to a specific local address, but it doesn't have to be.

The client, not the TCP/IP stack, selects the IP address.


FWIW, that local address could end up being any one of the addresses you find through System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(). It is not restricted to the ones you can see through Dns.GetHostEntry(Dns.GetHostName()), although the addresses registered in DNS are the most likely to be useful on a larger network. And the list of possible addresses can change, as a result of network connections making and breaking and also as a result of dynamically assigned address (DHCP) changes.

The System.Net.NetworkInformation.NetworkChange class can be used to find out when the local address list is updated.

Upvotes: 2

Andy
Andy

Reputation: 13567

In the docs for IPAddress.Any, it states:

The Socket.Bind method uses the Any field to indicate that a Socket instance must listen for client activity on all network interfaces.

By simply creating a TCPListener with this property, you tell the framework that you don't care which interface it uses, just pick the best one when something connects, not before.

In order for the framework to pick the best one, it needs a client to connect to it. When something connects, it chooses the best one for that instance at that time.

The next client that connects may get the same interface, or, it could get a different one because you choose IPAddress.Any

You state it in your question:

If you do not care which local address is assigned, specify IPAddress.Any for the localaddr parameter, and the underlying service provider will assign the most appropriate network address. ...If you use this approach, you can discover what local network address and port number has been assigned by using the LocalEndpoint property.

This is what you aren't understanding:

The emphasis above talks about the LocalEndpoint of the *Socket* that is created from accepting the connection -- not the listening TCPListener.

The docs could be more clear on this point, sure -- but once you understand how listeners work, this should click.

Upvotes: 2

Related Questions