在我工作的项目中含有多种操作系统、多种设备、多种开发语言,因此需要使用跨平台的通信技术和自定义的消息编码。经过技术调研,ZeroMQ+ProtocolBuffer最终成为通信技术和编码方式。但是如何使用这些技术成了问题,如果直接调用,势必会让业务逻辑和通信技术绑定在一起,很难分离。所以需要引入一种框架,可以将业务和通信解耦。WCF是目前最成熟的通信框架之一,WCF的优点还是很多的。
 
WCF连接各种通信技术,即可以封装各种通信技术。无论使用何种技术,设计服务端的方式是一致的;另一方面设计客户端的方式也是一致的,体现在:
  • 客户端调用的方式是一致的
  • 服务端处理请求的方式是一致的
  • 服务的实例管理的方式是一致的
  • 设计服务的操作模式的方式是一致的
  • 如果将自定义数据作为服务的参数,数据的定义是一致的
  • 处理异常的方式是一致的
  • 如果连接的通信技术支持事物,事物的处理是一致的

WCF可以隔离业务层和技术层,体现在:

  • 当客户端调用服务时,可以不需要知道服务端的实现语言和平台
  • 当服务端处理请求时,可以不需要知道客户端的实现语言和平台
  • 实现WCF的服务端时,只需要考虑业务接口的实现,另外接口和方法添加少量的属性、在配置中添加服务的地址
  • 实现WCF的客户端时,只需要按照协议调用服务,另外在配置中添加服务的地址
 
但是WCF默认绑定都是基于windows的,无法直接使用WCF内置的绑定。所以我就想既然WCF能集成MSMQ、tcp等一些通信技术,为什么我不能扩展WCF,并让其也集成ZeroMQ呢?
 
有想法了,说干就干。
 
经过近两周的努力,WCF的ZMQ扩展基本实现,能使用WCF的客户端或服务端与ZMQ的服务端或客户端相互通信。现在就将整体的设计介绍给大家。由于实现的步骤很多,这将会是一系列的文章。
 
WCF to ZMQ架构
 
部署图
WCF的ZMQ扩展的部署很简单,扩展分为ZMQBinding.dll和ProtocolBufferMessageExtension.dll两部分。ZMQBinding.dll负责将ZMQ集成到WCF中;ProtocolBufferMessageExtension.dll负责通信的数据编码和解析。这两部分将编码和传输分离开,使得编码和传输分别可以用其他方式实现。
 
组件图
当把WCF作为服务端,ZMQ作为客户端时,组件图为
 
 当把ZMQ作为服务端,WCF作为客户端时,组件图为:
无论哪种情况,WCF的服务端和客户端都只需要使用WCF的接口,而不需要了解ZMQ的技术细节。ZMQBinding和ProtocolBufferMessageExtension分别通过配置文件的方式注册到WCF中。当ZMQ发生请求或响应时,通过ZMQBinding中的ZMQ部分连接。ProtocolBufferMessageExtension的格式化器负责将消息体序列化或反序列化成基本类型或者ProtocolBuffer的数据访问类。消息验证器负责验证消息体的正确性,并把消息分发找到合适的WCF服务类的相应服务方法中。消息编码器负责将protocolBuffer的数据访问类编码成二进制数据。
 
使用WCF to ZMQ

虽然ZMQBinding和ProtocolBufferMessageExtension的做了很多转换工作,但是一旦将它们注册到WCF中,应用开发人员的工作量很小。

  • 当把WCF作为服务端,ZMQ作为客户端时,WCF服务端需要如下步骤:
1 定义WCF服务协议

   [ServiceContract]
public interface IService1
{
[OperationContract]
string UpdatePatients(WCF_Client_ZMQBinding.iStationMovementPos move);
}
2 实现服务类

 public class Service1 : IService1
{
public string UpdatePatients(WCF_Client_ZMQBinding.iStationMovementPos move)
{
return "wcf response";
}
}
3 定义服务协议所需要的业务实体类,如果服务协议中不含有复杂的实体类,这步可以省略。作为服务方法的参数,不需要添加DataContract属性,是因为自定义了数据的编码,而不是采用xml序列化的方式。

自定义数据编码是采用了反射的方式,把iStationMovementPos转成protocolBuffer的可序列化的类类型。

    public class iStationMovementPos
{
public int IhMaxPos{get;set;}
public int IhPos {get;set;}
public int IhMinPos{get;set;} public int IvMaxPos{get;set;}
public int IvPos {get;set;}
public int IvMinPos{get;set;} public int IaMaxPos{get;set;}
public int IaPos {get;set;}
public int IaMinPos{get;set;} public bool LaserStatus {get;set;}
public int CouchMarkPos { get; set; }
}
4 通过配置工具在配置文件中配置服务的地址、绑定类型(使用自定义的ZMQBindnig)、协议名(IService1)、服务行为(注册ProtocolBufferMessageExtension)
5 启动服务
ServiceHost host = new ServiceHost(typeof(Service1));
host.Open();
可见WCF的服务端使用起来非常方便,基本都是业务代码,没有涉及到连接技术(唯一指定连接技术的就是配置文件)。而客户端是完全的ZeroMQ代码,不需要任何WCF的依赖,客户端可以是Android、也可以是linux。
 
  • 当把ZMQ作为服务端,WCF作为客户端时,WCF客户端需要如下步骤:
WCF客户端和WCF的服务端的步骤相似,服务接口和服务类如下:
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName = "ServiceReference1.IService1")]
public interface IService1
{ [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService1/DoWork", ReplyAction = "http://tempuri.org/IService1/DoWorkResponse")]
[ProtocolBufferMessageExtension.Formatter.PBFormatMessage]
string DoWork(iStationMovementPos move); [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService1/DoWork", ReplyAction = "http://tempuri.org/IService1/DoWorkResponse")]
System.Threading.Tasks.Task<string> DoWorkAsync(iStationMovementPos move);
} [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface IService1Channel : Client.ServiceReference1.IService1, System.ServiceModel.IClientChannel
{
} [System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class Service1Client : System.ServiceModel.ClientBase<Client.ServiceReference1.IService1>, Client.ServiceReference1.IService1
{ public Service1Client()
{
} public Service1Client(string endpointConfigurationName) :
base(endpointConfigurationName)
{
} public Service1Client(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
} public Service1Client(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
} public Service1Client(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public string DoWork(iStationMovementPos move)
{
return base.Channel.DoWork(move);
}
public System.Threading.Tasks.Task<string> DoWorkAsync(iStationMovementPos move)
{
return base.Channel.DoWorkAsync(move);
}
}
也是通过配置工具在配置文件中配置。
调用代码非常简单:
            iStationMovementPos move = new iStationMovementPos()
{
IhMaxPos = ,
IhMinPos = ,
IaPos = ,
IaMaxPos = ,
IaMinPos = ,
IhPos = ,
IvMaxPos = ,
IvMinPos = ,
IvPos = ,
LaserStatus = true,
CouchMarkPos =
};
Service1Client client = new Service1Client();
string res = client.DoWork(move);
而服务端是完全的ZeroMQ代码,不需要任何WCF的依赖,服务端可以是linux平台的GPC。
第一篇暂时介绍到这。

WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(一)概要设计的更多相关文章

  1. WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(二)实现IRequestChannel(2016-03-15 12:35)

    这是这个系列的第二篇,其他的文章请点击下列目录 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(一)概要设计 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息 ...

  2. WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(三)实现ReplyChannel(2016-03-15 12:35)

    这是这个系列的第三篇,其他的文章请点击下列目录 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(一)概要设计 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息 ...

  3. WCF扩展系列 - 行为扩展(Behaviors)

    原文地址:http://www.cnblogs.com/Creator/archive/2011/05/21/2052687.html 这个系列的第一部分将会重点关注WCF行为(behaviors), ...

  4. 【转】WCF扩展系列 - 行为扩展(Behaviors)

    原文:https://www.cnblogs.com/Creator/archive/2011/05/21/2052687.html 这个系列的第一部分将会重点关注WCF行为(behaviors),W ...

  5. 真实世界:使用WCF扩展记录服务调用时间

    WCF 可扩展性 WCF 提供了许多扩展点供开发人员自定义运行时行为. WCF 在 Channel Layer 之上还提供了一个高级运行时,主要是针对应用程序开发人员.在 WCF 文档中,它常被称为服 ...

  6. WCF 服务的ABC之绑定(六)

    绑定 Binding 绑定是开发人员控制WCF程序与其他消息交互的主要手段.从功能上看,绑定创建了通道工厂惑通道侦听器的堆栈对象.绑定直接惑间接创建的对象是WCF实现各种消息功能(例如,传输.安全性. ...

  7. WCF扩展

    WCF 可扩展性 WCF 提供了许多扩展点供开发人员自定义运行时行为. WCF 在 Channel Layer 之上还提供了一个高级运行时,主要是针对应用程序开发人员.在 WCF 文档中,它常被称为服 ...

  8. 扩展SpringMVC以支持绑定JSON格式的请求参数

    此方案是把请求参数(JSON字符串)绑定到java对象,,@RequestBody是绑定内容体到java对象的. 问题描述: <span style="font-size: x-sma ...

  9. WCF 项目应用连载[8] - 绑定、服务、行为 大数据传输与限流 - 下 (ServiceThrottlingAttribute)

    因为ORM的原因,对Attribute编程有一种情节..所以这节的出现,完全是因为在WCF对自定义Attribute的一种应用. WCF 项目应用连载[7] - 绑定.服务.行为 大数据传输与限流 - ...

随机推荐

  1. 浅析Delphi Container库(有开源的DCLX)

    与Java和C++相比,Delphi对容器的支持实在少得可怜.Java有强大的集合框架,C++更有STL,Delphi有什么呢,不就是TList几个小巧的列表类,而TCollection系列的类更多只 ...

  2. Delphi主窗口任务栏菜单的问题(转发WM_SYSCOMMAND到Application)

    Delphi的VCL框架在创建应用时TApplication是一个自动创建的隐藏窗口,其它创建的窗口是自动以该窗口为窗口,这就导致创始的主窗口在任务栏的系统菜单只有三项,只要在主窗口的Create事件 ...

  3. sqlserver 自学笔记 函数实训 学分学期转换函数的设计

    设计目的: 1.运用sql基本知识,编写学期转换函数. 2.运用sql基本知识,编写学分转换函数,将考试成绩转换为学分 3.通过上述函数的编写与调试,熟练掌握 sql函数的编写.调试与使用方法. 设计 ...

  4. Delphi中编写无输出函数名的DLL文件(有点意思)(400多篇博客)

    用 Delphi 用长了,总是发现,有些和 MS 不同的地方.例如,MS 的公开库中,常常隐藏了许多重要函数,这些函数在系统中常常有起着非常巨大的作用.一旦知道如何调用,可以给自己的应用程序提供很强的 ...

  5. AMFPHP1.4与PHP5.3及以上版本号不兼容问题的解决

    近期在升级PHP5.4版本号,AMFPHP出现了兼容性问题.解决过程记录例如以下. 1.ereg类相关函数改动为preg相关函数. 2.通过错误日志输出的提示.将全部以静态方式调用的类函数加入stat ...

  6. C语言内存对齐

    转:http://blog.csdn.net/embeddedman/article/details/7429976 首先由一个程序引入话题:  1 //环境:vc6 + windows sp2 2  ...

  7. 30天自制操作系统第九天学习笔记(u盘软盘双启动版本)

    暑假学习小日本的那本书:30天自制操作系统 qq交流群:122358078    ,更多学习中的问题.资料,群里分享 environment:开发环境:ubuntu 第九天的课程已学完,确实有点不想写 ...

  8. GB2312引进和使用的字体

    一个:先上图看到的结果,下面的屏幕截图android在测试的结果"SD卡测试".."GPS测试"和其他字符24x24字体进来. 二:  1)简单介绍       ...

  9. JavaScript2谁刚开始学习应该知道4最佳实践文章(翻译)

    原版的:24 JavaScript Best Practices for Beginners (注:阅读原文的时候没有注意公布日期,觉得不错就翻译了,翻译到JSON.parse那一节觉得有点不正确路才 ...

  10. 浅谈OCR之Onenote 2010

    原文:浅谈OCR之Onenote 2010 上一次我们讨论了Tesseract OCR引擎的用法,作为一款老牌的OCR引擎,目前已经开源,最新版本3.0中更是加入了中文OCR功能,再加上Google的 ...