简单的WCF发布-订阅(Pub/Sub)服务

来源:互联网 发布:mac不用鼠标右键 编辑:程序博客网 时间:2024/06/05 18:04

简单的WCF发布-订阅(Pub/Sub)服务

    发布-订阅服务架构是分布式系统中常见的服务架构。本文将通过一个简单的例子介绍WCF中发布-订阅服务的实现,以及一些相关概念的介绍。

    WCF支持回调操作,所谓回调就是服务端调用客户端的操作。如下图所示,在回调时:服务成为客户端,客户端成为服务。

    回调服务结构

    本文要实现的例子是这样的:客户端(订阅者)向服务(发布者)提出订阅请求,服务响应客户端请求,并通过回调客户端上的操作来通知客户端。

    一、契约

    所谓契约就是大家都有遵守的东西。发布-订阅模式的契约和其他回调服务一样分为两个部分:服务契约和回调契约。

    1.1 服务契约

    

  1. [ServiceContract(CallbackContract=typeof(ICallbackEvents))]
  2.     public interface IPublishService
  3.     {
  4.         [OperationContract(IsOneWay=true)]
  5.         void Subscribe(Guid id);
  6.         [OperationContract(IsOneWay=true)]
  7.         void UnSubscribe(Guid id);
  8.         
  9.     }

    服务契约提供了订阅Subscribe( )和退订UnSubscibe( )两个服务操作。两个操作的参数都是GUID,主要是区分各个订阅者。

    将ServiceContract的CallbackContract属性定义为ICallbackEvents,即是指明回调契约。

    1.2 回调契约

    

  1. public interface ICallbackEvents
  2.     {
  3.         [OperationContract(IsOneWay=true)]
  4.         void Notify();
  5.     }

    回调契约定义了一个Notify( )操作,是用于服务通知客户端的。

    回调契约之所以不用加[ServiceContract],是因为在服务契约中已经指明了。

    

    二、服务

    

  1. [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.Single)]
  2.     public class PublishService : IPublishService
  3.     {
  4.         public List<Guid> list_SubscrberId = new List<Guid>();
  5.         public List<ICallbackEvents> list_Callback = new List<ICallbackEvents>();
  6.         public void Subscribe(Guid id)
  7.         {
  8.             
  9.             if (list_SubscrberId.IndexOf(id) < 0)//如果不存在,则添加
  10.             {
  11.                 list_SubscrberId.Add(id);
  12.                 ICallbackEvents callback = OperationContext.Current.GetCallbackChannel<ICallbackEvents>();
  13.                 list_Callback.Add(callback);
  14.             }    
  15.             
  16.         }
  17.         public void UnSubscribe(Guid id)
  18.         {
  19.             list_Callback.RemoveAt(list_SubscrberId.IndexOf(id));
  20.             list_SubscrberId.Remove(id);
  21.         }
  22.     }

    服务实现了订阅Subscribe( )和退订UnSubscibe( )两个操作。并且定义了两个链表分别保存订阅者的ID和 他的回调操作的上下文。两个链表的项是依次对应的。其中,ID链表是和下面的主机进程的ListBox是“绑定”。

    需要强调的是,我们在这把ServiceBehavior设为可重入的来实现回调功能。将其实例模式设置为单例模式,以让多个订阅者公用一个发布者。

 

    三、主机

    

    

  1. public partial class PublishForm : Form
  2.     {
  3.         private PubSub_Srv.PublishService pubsrv = new PubSub_Srv.PublishService();
  4.         private ServiceHost host;
  5.         public PublishForm()
  6.         {
  7.             InitializeComponent();
  8.         }
  9.         private void Form1_Load(object sender, EventArgs e)
  10.         {
  11.             host = new ServiceHost(pubsrv);
  12.             host.Open();
  13.         }
  14.         private void btn_Stop_Click(object sender, EventArgs e)
  15.         {
  16.             host.Close();
  17.         }
  18.         private void btn_NotifyAll_Click(object sender, EventArgs e)
  19.         {
  20.             for (int i = 0; i < pubsrv.list_SubscrberId.Count; i++)
  21.             {
  22.                 
  23.                 try
  24.                 {
  25.                     pubsrv.list_Callback[i].Notify();
  26.                 }
  27.                 catch(Exception ex)
  28.                 {
  29.                     MessageBox.Show(ex.Data.ToString()+"/n无法连接客户:/n"+pubsrv.list_SubscrberId[i].ToString());
  30.                 }
  31.             }
  32.         }
  33.         private void btn_Refresh_Click(object sender, EventArgs e)
  34.         {
  35.             listBox_SubsciberID.Items.Clear();
  36.             for (int i = 0; i < pubsrv.list_SubscrberId.Count; i++)
  37.                 listBox_SubsciberID.Items.Add(pubsrv.list_SubscrberId[i].ToString());
  38.         }
  39.     }

    主机进程是一个WindowsForm的应用程序,提供服务的承载和图像界面。

 

    四、客户端

 

 

 

  1. public partial class SubsciberForm : Form
  2.     {
  3.         private Guid Myid;
  4.         private PubSub_Srv_Ref.PublishServiceClient client;
  5.         public SubsciberForm()
  6.         {
  7.             InitializeComponent();
  8.             Myid = System.Guid.NewGuid();
  9.             this.Text = Myid.ToString();
  10.             CallbackEvents callback = new CallbackEvents();
  11.             InstanceContext context = new InstanceContext(callback);
  12.             client = new Subscriber.PubSub_Srv_Ref.PublishServiceClient(context);
  13.         }
  14.         private void SubsciberForm_Load(object sender, EventArgs e)
  15.         {
  16.         }
  17.         private void btn_Subscibe_Click(object sender, EventArgs e)
  18.         {
  19.             if (client == null)
  20.             {
  21.                 CallbackEvents callback = new CallbackEvents();
  22.                 InstanceContext context = new InstanceContext(callback);
  23.                 client = new Subscriber.PubSub_Srv_Ref.PublishServiceClient(context);
  24.             }
  25.             client.Subscribe(Myid);
  26.         }
  27.         private void btn_UnSubscibe_Click(object sender, EventArgs e)
  28.         {
  29.             client.UnSubscribe(Myid);
  30.             client.Close();
  31.         }
  32.     }

    五、配置    

    最后要说明的是,要实现回调服务必须使用具有双向通信功能的绑定方式,如netTcpBinding。

    另外为了在为了在网络上运行,需要将<security mode="None">

 

本文代码下载:http://download.csdn.net/source/605896

原创粉丝点击