How can I get the port that a WCF service is listening on?
Asked Answered
H

3

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
Hoofbeat answered 25/8, 2010 at 6:38 Comment(3)
It's quite unusual to get a service to listen on a random port - is there a reason you want to do this?Siege
@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.Hoofbeat
possible duplicate of How can I get the listening address/port of a WCF service?Fanciful
F
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!

Folberth answered 25/8, 2010 at 6:53 Comment(3)
@D Hoerster: unfortunately that just gives back the URI that I passed in. Thanks for the pointer to the other question.Hoofbeat
@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).Hoofbeat
Did you make your call to Open?Xanthippe
G
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());
Goosander answered 26/8, 2010 at 15:0 Comment(0)
S
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.

Siege answered 25/8, 2010 at 7:5 Comment(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.Ragi

© 2022 - 2024 — McMap. All rights reserved.