Silverlight 3 wcf 双工通信

在silverlight3中对wcf的双工通信有了很多的进展,当然是相对我大半年前研究这技术点的时候,还记得当时一系列问题都是无法得到解决的,使用上与常规的wcf也有着很大的区别,没有对wcf有深入理解的朋友是不可以用当时的它来开发实际的项目的,像序列化、直接抽像方法名等都是令人头痛的问题,所以一直不想提及sl中的此技术。

直到现在sl3的降临把当时的一系列问题的解决了,而且性能也有所提高,应用的时候和传统的wcf有了相当的相似度,那么不值得说述一下了。

以下演示的是silverlight3中使用wcf的pulling duplex的一个比效简单的双工应用,本来是想直接做一个聊天室的应用,发现还有一些问题是没有解决的,所以先写下这个简单的应用,以后待问题解决后再作为应用来讲述这个技术。

1.我们的 Wcf 服务将会使用 Silverlight 3 SDK 附带的 PollingDuplex。
要添加对 System.ServiceModel.PollingDuplex 程序集的引用:

2.WCF 服务和回调合同的创建
创建 Silverlight 启用 WCF 服务和 回调契约
回调契约是用于 WCF 服务向 Silverlight 客户端推送数据的接口:

1:  public interface IDuplexServiceCallback
2:  {
3:      [OperationContract(IsOneWay = true)]
4:      void GetData(string data);
5:  }

请注意 GetData 方法是用 OperationContract 属性标识的,并且 IsOneWay 参数设置为 true

3.使用回调契约链接 WCF 服务。
用标识为 ServiceContract 属性的WCF服务,并将 CallbackContract 设置为有效的类型:

 1:  [ServiceContract(Namespace = "", CallbackContract = typeof(IDuplexServiceCallback))]
 2:  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
 3:  public class Service1
 4:  {
 5:      [OperationContract]
 6:      public void DoWork()
 7:      {
 8:          //.............
 9:      }
10:  }

4.将数据推送到客户端之调用回调合同方法。
要将数据发送到客户端,我们首先必须获得一个有效的回调通道和调用的方法之一。

在本例中我们通过调用 OperationContext.Current.GetCallbackChannel <iduplexservicecallback>获取回调通道)

并调用它的 GetData() 方法把数据推送至所有在线的客户端:

 1:  [ServiceContract(Namespace = "", CallbackContract = typeof(IDuplexServiceCallback))]
 2:  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
 3:  public class Service1
 4:  {
 5:      //我使用了这个实例来存放所有的已成功连接服务器端的客户端
 6:      static List<IDuplexServiceCallback> cilents = new List<IDuplexServiceCallback>();
 7:  
 8:      [OperationContract]
 9:      public void DoWork()
10:      {
11:          cilents.Add(OperationContext.Current.GetCallbackChannel<IDuplexServiceCallback>());
12:  
13:          for (int i = 0; i <= cilents.Count - 1; i++)
14:          {
15:              cilents[i].GetData("new user logined");
16:          }
17:      }
18:  }

5.创建Service Host Factory。

由于目前不支持 web.config 中配置服务。

我们要手动去创建 Service Host Factory 提供服务终结点配置:

 1:  public class PollingDuplexServiceHostFactory : ServiceHostFactoryBase
 2:  {
 3:      public override ServiceHostBase CreateServiceHost(string constructorString,
 4:          Uri[] baseAddresses)
 5:      {
 6:          return new PollingDuplexSimplexServiceHost(baseAddresses);
 7:      }
 8:  }
 9:  
10:  class PollingDuplexSimplexServiceHost : ServiceHost
11:  {
12:      public PollingDuplexSimplexServiceHost(params System.Uri[] addresses)
13:      {
14:          base.InitializeDescription(typeof(jacDuplex.Web.Service1), new UriSchemeKeyedCollection(addresses));
15:          base.Description.Behaviors.Add(new ServiceMetadataBehavior());
16:      }
17:  
18:      protected override void InitializeRuntime()
19:      {
20:          // Add an endpoint for the given service contract.
21:          this.AddServiceEndpoint(
22:              typeof(jacDuplex.Web.Service1),
23:              new CustomBinding(
24:                  new PollingDuplexBindingElement(),
25:                  new BinaryMessageEncodingBindingElement(),
26:                  new HttpTransportBindingElement()),
27:                  "");
28:  
29:          // Add a metadata endpoint.
30:          this.AddServiceEndpoint(
31:              typeof(IMetadataExchange),
32:              MetadataExchangeBindings.CreateMexHttpBinding(),
33:              "mex");
34:  
35:          base.InitializeRuntime();
36:      }
37:  }

最后,让我们应用该Factory到服务:

1:  <%@ ServiceHost Language="C#" Debug="true" Service="jacDuplex.Web.Service1" CodeBehind="Service1.svc.cs" Factory="Silverlight.Client.Web.Services.PollingDuplexServiceHostFactory" %>

请注意有运行此服务之前请先把web.config文件中所有wcf相关的配置都删除。

7. 在Silverlight 项目添加服务引用 。

请注意我们要添加双工服务的引用时 ServiceReferences.ClientConfig 不会产生内容,因此我们必须手动将端点和地址的配置传递给服务客户端:

1:  EndpointAddress address = new EndpointAddress("http://localhost:2244/Service1.svc");
2:  
3:  CustomBinding binding = new CustomBinding(
4:      new PollingDuplexBindingElement(),
5:      new BinaryMessageEncodingBindingElement(),
6:      new HttpTransportBindingElement());
7:  
8:  ServiceReference1.Service1Client client = new jacDuplex.ServiceReference1.Service1Client(binding, address);

8. 使用服务
使用双工的服务非常简单。

我们只要处理 GetDataReceived 事件 (因为我们的回调契约公开的是 GetData 方法),并让 WCF 处理客户端/服务器通信

image

上图中,一共有两个客户端,每个客户端登陆时都会通知其他所有客户端有一个新的用户登陆。

结束语:

尽管目前silverlight 3中对wcf的双式支持还未达到完美的境地,但相对之前已经是一个飞跃的进步。剩下的一个些问题还有待研究去决解,相信那只是我对它未有更加深入的了解而产生的疑问,相信很快会得到解决,例如:捕抓异常的客户端等。

你可能感兴趣的:(silverlight)