Multiple channels


**** One of my colleagues has pointed out a bug in this example ****


I have edited this so that it now shows the correct code.


The bug is that for Peer channel the configuration for each endpoint needs a distinct address to see what has changed please view the section labeled The Configuration


the update items are italicized.


*********************************************************


Updated to reflect changes in the February CTP


*********************************************************


In my previous post (can be found: here) I showed how to write a very simple Peer channel app with a single Message type “Say”.  In this post I will show you how to extend it so that it contains multiple channels, each of which have different messages.


The application consists of 2 ServiceContracts, IHelloMessage for talking and IStatus for propogating information about how busy a member is.


The Contracts


  [ServiceContract(Namespace = “urn:uuid:F0E619F9-3AB7-4b9d-A009-269B381C6C85/”, CallbackContract = typeof(IHelloMesh))]


  interface IHelloMesh


  {


    [OperationContract(IsOneWay = true)]


    void Say(string message);


  }


 


  [ServiceContract(Namespace = “urn:uuid:F0E619F9-3AB7-4b9d-A009-269B381C6C85/”, CallbackContract = typeof(IStatus))]


  interface IStatus


  {


    [OperationContract(IsOneWay = true)]


    void Busy(string userId);


 


    [OperationContract(IsOneWay = true)]


    void NotBusy(string userId);


  }


IHelloMesh is as described in my previous post.  IStatus defines a new ServiceContract with 2 operations Busy() and NotBusy()


The Proxies


  partial class HelloProxy : System.ServiceModel.DuplexClientBase<IHelloMesh>, IHelloMesh


  {


    public HelloProxy(InstanceContext inputInstance, string name)


        : base(inputInstance, name)


    {


        base.InnerDuplexChannel.Open();


    }


 


    public void Say(string message)


    {


      base.InnerProxy.Say(message);


    }


  }


 


  partial class StatusProxy : System.ServiceModel.DuplexClientBase<IStatus>, IStatus


  {


    public StatusProxy(InstanceContext inputInstance, string name)


         : base(inputInstance, name)


    {


      base.InnerDuplexChannel.Open();


    }


 


    public void Busy(string userId)


    {


      base.InnerProxy.Busy(userId);


    }


 


    public void NotBusy(string userId)


    {


        base.InnerProxy.NotBusy(userId);


     }


  }


Again HelloProxy is unchanged, I have Added a StatusProxy so that the application can be used to send status messages to the mesh.


The Main is somewhat different, instead of a using {} I have a try {} finally {} mainly to show a different way of achieving the same result.  To send a NotBusy message just enter a line that begins with “notbusy”.  To send a Busy type a line that begins with “busy”.  To quit enter “q”.


  class Program


  {


    static void Main(string[] args)


    {


      Console.WriteLine(“Please enter your id”);


      string id = Console.ReadLine();


      InstanceContext instanceContext = new InstanceContext(new HelloMesh());


      using (HelloProxy hello = new HelloProxy(instanceContext, “HelloEndpoint”))


      {


        using (StatusProxy status = new StatusProxy(instanceContext, “StatusEndpoint”))


        {


          string msg = “”;


          while (msg != “q”)


          {


            msg = Console.ReadLine();


            if (msg.StartsWith(“busy”, StringComparison.CurrentCultureIgnoreCase))


            {


              status.Busy(id);


            }


            else if (msg.StartsWith(“notbusy”, StringComparison.CurrentCultureIgnoreCase))


            {


              status.NotBusy(id);


            }


            else


            {


              hello.Say(msg);


            }


          }


        }


      }


    }


  }


 


The Complete Program


using System;


using System.Collections.Generic;


using System.ServiceModel;


using System.Text;


 


namespace HelloMesh


{


  [ServiceContract(Namespace = “urn:uuid:F0E619F9-3AB7-4b9d-A009-269B381C6C85/”, CallbackContract = typeof(IHelloMesh))]


  interface IHelloMesh


  {


    [OperationContract(IsOneWay = true)]


    void Say(string message);


  }


 


  [ServiceContract(Namespace = “urn:uuid:F0E619F9-3AB7-4b9d-A009-269B381C6C85/”, CallbackContract = typeof(IStatus))]


  interface IStatus


  {


    [OperationContract(IsOneWay = true)]


    void Busy(string userId);


 


    [OperationContract(IsOneWay = true)]


    void NotBusy(string userId);


  }


 


  partial class HelloProxy : System.ServiceModel.DuplexClientBase<IHelloMesh>, IHelloMesh


  {


    public HelloProxy(InstanceContext inputInstance, string name)


        : base(inputInstance, name)


    {


        base.InnerDuplexChannel.Open();


    }


 


    public void Say(string message)


    {


      base.InnerProxy.Say(message);


    }


  }


 


  partial class StatusProxy : System.ServiceModel.DuplexClientBase<IStatus>, IStatus


  {


    public StatusProxy(InstanceContext inputInstance, string name)


         : base(inputInstance, name)


    {


      base.InnerDuplexChannel.Open();


    }


 


    public void Busy(string userId)


    {


      base.InnerProxy.Busy(userId);


    }


 


    public void NotBusy(string userId)


    {


        base.InnerProxy.NotBusy(userId);


     }


  }


 


  class HelloMesh : IHelloMesh, IStatus


  {


    public void Say(string message)


    {


      Console.WriteLine(“Say : {0}”, message);


    }


 


    public void Busy(string userId)


    {


      Console.WriteLine(“User {0} is busy”, userId);


    }


 


    public void NotBusy(string userId)


    {


      Console.WriteLine(“User {0} is not busy”, userId);


    }


  }


 


  class Program


  {


    static void Main(string[] args)


    {


      Console.WriteLine(“Please enter your id”);


      string id = Console.ReadLine();


      InstanceContext instanceContext = new InstanceContext(new HelloMesh());


      using (HelloProxy hello = new HelloProxy(instanceContext, “HelloEndpoint”))


      {


        using (StatusProxy status = new StatusProxy(instanceContext, “StatusEndpoint”))


        {


          string msg = “”;


          while (msg != “q”)


          {


            msg = Console.ReadLine();


            if (msg.StartsWith(“busy”, StringComparison.CurrentCultureIgnoreCase))


            {


              status.Busy(id);


            }


            else if (msg.StartsWith(“notbusy”, StringComparison.CurrentCultureIgnoreCase))


            {


              status.NotBusy(id);


            }


            else


            {


              hello.Say(msg);


            }


          }


        }


      }


    }


  }


}


 


The Configuration


The configuration is extended with the specification of a new endpoint for the IStatus contract:


<?xml version=1.0 encoding=utf-8 ?>


<configuration xmlns=http://schemas.microsoft.com/.NetConfiguration/v2.0>


  <system.serviceModel>


    <client>


      <endpoint name=HelloEndpoint


                address=net.p2p://hellomesh/helloendpoint


                binding=netPeerTcpBinding


                bindingConfiguration=Binding1


                contract=HelloMesh.IHelloMesh>


      </endpoint>


      <endpoint name=StatusEndpoint


                address=net.p2p://hellomesh/statusendpoint


                binding=netPeerTcpBinding


                bindingConfiguration=Binding1


                contract=HelloMesh.IStatus>


      </endpoint>


    </client>


    <bindings>


      <netPeerTcpBinding>


        <binding name=Binding1


                 port=5182>


          <security mode=None/>


        </binding>


      </netPeerTcpBinding>


    </bindings>


  </system.serviceModel>


</configuration>


Run


Compile and build copy the exe and config to 2 windows XP machines, start up each instance.  Type hello, world in one watch the message appear ion both.  Then type busy and observe the Busy message appear on both machines, enter notbusy and observe the not busy message.