8

I have a net.tcp WCF service, and I would like the OS to pick the port that it should listen on. So I have set the port to 0 in my URI, and netstat confirms that the OS has picked a port in the 5000 range.

How can I find the actual port that has been picked, in code, inside the service process?

Some code to show what I have tried:

Type serviceType = ...;
Uri address = new Uri("net.tcp://0.0.0.0:0/Service/");
ServiceHost serviceHost = new ServiceHost(serviceType, address);
ServiceEndpoint endPoint = serviceHost.AddServiceEndpoint(type, binding, "");
int port1 = endPoint.ListenUri.Port; // returns 0
int port2 = serviceHost.BaseAddresses.First().Port; // also returns 0
ngoozeff
  • 4,576
  • 3
  • 28
  • 21
  • It's quite unusual to get a service to listen on a random port - is there a reason you want to do this? – Cocowalla Aug 25 '10 at 06:45
  • 1
    @Cocowalla: The service is part of a worker process, so there can be more than one at time, and we're looking at solutions that don't involve .NET TCP Port Sharing. – ngoozeff Aug 25 '10 at 06:51
  • possible duplicate of [How can I get the listening address/port of a WCF service?](http://stackoverflow.com/questions/2207348/how-can-i-get-the-listening-address-port-of-a-wcf-service) – mafu Apr 18 '12 at 11:08

3 Answers3

11

Not sure if this will help, but there's a similar question already on SO: How can I get the listening address/port of a WCF service?

The relevant part of a submitted answer that you may want to try:

foreach (var channelDispatcher in serviceHost.ChannelDispatchers)
{
            Console.WriteLine(channelDispatcher.Listener.Uri);
}

So maybe you need channelDispatcher.Listener.Uri.Port.

Hope this helps!

Community
  • 1
  • 1
David Hoerster
  • 28,421
  • 8
  • 67
  • 102
  • 2
    @D Hoerster: unfortunately that just gives back the URI that I passed in. Thanks for the pointer to the other question. – ngoozeff Aug 25 '10 at 07:22
  • 4
    @D Hoerster: Looks like we have a winner. I also had to set endPoint.ListenUriMode = ListenUriMode.Unique; for this to work (and disable port sharing on the binding). – ngoozeff Aug 27 '10 at 06:15
  • Did you make your call to Open? – BozoJoe May 11 '12 at 20:38
3

Once the service has started you can get a full description of the endpoints that were actually created from the Description.Endpoints collection (this doesn't work until after Open() is called). From this collection you can get the address. Unfortuantely you have to string parse the address for the port.

This is what my server logs after every service Open().

        serviceHost.Open();

        // Iterate through the endpoints contained in the ServiceDescription 
        System.Text.StringBuilder sb = new System.Text.StringBuilder(string.Format("Active Service Endpoints:{0}", Environment.NewLine), 128);
        foreach (ServiceEndpoint se in serviceHost.Description.Endpoints)
        {
            sb.Append(String.Format("Endpoint:{0}", Environment.NewLine));
            sb.Append(String.Format("\tAddress: {0}{1}", se.Address, Environment.NewLine));
            sb.Append(String.Format("\tBinding: {0}{1}", se.Binding, Environment.NewLine));
            sb.Append(String.Format("\tContract: {0}{1}", se.Contract.Name, Environment.NewLine));
            foreach (IEndpointBehavior behavior in se.Behaviors)
            {
                sb.Append(String.Format("Behavior: {0}{1}", behavior, Environment.NewLine));
            }
        }

        Console.WriteLine(sb.ToString());
ErnieL
  • 5,773
  • 1
  • 23
  • 27
1

As an alternative, you could find a free port for WCF to use yourself:

private int FindPort()
{
    IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);

    using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
    {
         socket.Bind(endPoint);
         IPEndPoint local = (IPEndPoint)socket.LocalEndPoint;
         return local.Port;
    }
}

Code from here.

Cocowalla
  • 13,822
  • 6
  • 66
  • 112
  • 1
    This is not safe. Someone else can snatch the port after the socket is disposed but before the ServiceHost is opened. So this method may fail sporadically. – BatteryBackupUnit Jul 21 '14 at 12:09