Finding available callback tcp port for a WCF chat client

While having some fun writing a WCF chat application, I was having some troubles.

I was using duplex communication over http, using the WsDualHttpBinding. The client needs to setup a callback channel for the service to… well, call back actually. Hence the name, I guess 😉 Anyway, by default it wants to create this channel on port 80, which wasn’t possible because IIS is already listening on that port. For that you need to specify the ClientbaseAddress on your binding.

DuplexChannelFactory<IChatService> dcf = new DuplexChannelFactory<IChatService>(client, "ChatService");
Uri uri = new Uri(@"http://localhost:8000/callbackchannel");
((WSDualHttpBinding)dcf.Endpoint.Binding).ClientBaseAddress = uri;

Now the callback channel is on port 8000. But, you might want to start multiple clients to test your service. So you need to know what port isn’t taken yet. I wasn’t the first to ask this question, but either I’m really lousy in searching Google, or nobody has blogged a complete answer yet. Either way, here’s what I used.

int selectedPort = 8000;
bool goodPort = false;
IPAddress ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
//
while (!goodPort)
{
 
  IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, selectedPort);
  TcpListener list = new TcpListener(ipLocalEndPoint);
  try
  {
    list.Start();
    goodPort = true;
    list.Stop();
  }
  catch
  {
    selectedPort++;
  }
}

There you go, now you know as well.

Update : Was having some problems with CopySourceAsHtml after changing some settings. Should work now.

You may also like...

9 Responses

  1. Waseem Sadiq says:

    Dennis,

    There might be an easier way for doing this (works with peerChannel, not sure about regular callbacks), check it out:

    http://blogs.msdn.com/kevin_ransom/archive/2006/06/10/Automatic-port-number-generation.aspx

  2. I saw the duplex option at Tech-Ed. I was really impressed with that option.

  3. Waseem, I tried the port 0 in code, as I read somewhere else (not a WCF reference) that it would use any available port. But it returned an error.

    Will try it again using config though, perhaps it’ll work than.

  4. Mohamed Amine AZZI says:

    Hi Dennis,
    Did you use a web client or windows forms clients for your chat application?

    I need to know how to make a dual communnication when using asp.net pages.

    Regards

  5. Hazem Salem says:

    Hi Dennis, I’m also interesting to use this dual application with wep.net page, did you make it before?
    best reards

  6. @Hazem: I seriously have no idea what you’re talking about, sorry 🙂

  7. Mike says:

    Try this instead:

    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;
    }

  8. jimi says:

    hi,
    i m trying to use Duplex channel factory along with te to create a IClientChannel to create a pda chat client. both are not support in .net 3.5 WCF. Any one has done a WCF chat app ?

    jimi

  9. Robbert says:

    Hi Dennis,

    You can find some good explanations here:

    http://codeidol.com/csharp/wcf/Operations/Callback-Operations/

    In the book Programming WCF Services written by Juval Lowy, there is some code, that can let you set the port to any free port.
    It can be done by attributes, but the simple thing is do it programmaticly with a helperClass.

    public static class WsDualProxyHelper
    {
    public static void SetClientBaseAddress(DuplexClientBase proxy,int port) where T : class
    {
    if(proxy.State == CommunicationState.Opened)
    {
    throw new InvalidOperationException(“Proxy is already opened”);
    }
    WSDualHttpBinding binding = proxy.Endpoint.Binding as WSDualHttpBinding;
    Debug.Assert(binding != null);

    binding.ClientBaseAddress = new Uri(“http://localhost:” + port +”/”);
    }
    public static void SetClientBaseAddress(DuplexClientBase proxy) where T : class
    {
    lock(typeof(WsDualProxyHelper))
    {
    int portNumber = FindPort();
    SetClientBaseAddress(proxy,portNumber);
    proxy.Open();
    }
    }
    internal static 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;
    }
    }
    }

    After declaring the proxy, just assign clientBaseAddress like this:
    WsDualProxyHelper.SetClientBaseAddress(proxy); or WsDualProxyHelper.SetClientBaseAddress(proxy, 3000);

Click on a tab to select how you'd like to leave your comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.