tags:

views:

60

answers:

3

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
+1  A: 

Not sure if this will help, but there's a similar question already on SO: http://stackoverflow.com/questions/2207348/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!

David Hoerster
@D Hoerster: unfortunately that just gives back the URI that I passed in. Thanks for the pointer to the other question.
ngoozeff
@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
+1  A: 

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
+1  A: 

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
+1 for getting me on the right track
ngoozeff