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="https://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.