请求过程中的回调

这是一种比较典型的双工消息交换模式的表现形式,客户端在进行服务调用的时候,附加上一个回调对象;服务在对处理该处理中,通过客户端附加的回调对象(实际上是调用回调服务的代理对象)回调客户端的操作(该操作在客户端执行)。整个消息交换的过程实际上由两个基本的消息交换构成,其一是客户端正常的服务请求,其二则是服务端对客户端的回调。两者可以采用请求-回复模式,也可以采用单向(One-way)的MEP进行消息交换。图1描述了这样的过程,服务调用和回调都采用请求-回复MEP。

我们沿用计算服务的例子。在这之前,我们都是调用CalculuateService直接得到计算结果,并将计算结果通过控制台输出。在本例中我们将采用另外一种截然不同的方式调用服务并进行结果的输出:我们通过单向(One-way)的模式调用CalculuateService(也就是客户端不可能通过回复消息得到计算结果),服务端在完成运算结果后,通过回调(Callback)的方式在客户端将计算结果打印出来。

一:定义服务契约和回调契约

首先进行服务契约的定义,我们照例通过接口(ICalculator)的方式定义服务契约,作用于指定加法运算的Add操作,我们通过OperationContractAttribute特性的IsOneway属性将操作定义成单向的操作,这意味着客户端仅仅是向服务端发送一个运算的请求,并不会通过回复消息得到任何运算结果。

[ServiceContract(Namespace = "http://www.artech.com/", CallbackContract = typeof(ICallback))]//回调契约的类型通过ServiceContractAttribute特性的CallbackContract属性进行指定。
public interface ICalculator
{
[OperationContract(IsOneWay = true)]
void Add(double x, double y);
}
//回调契约
public interface ICallback //由于定义ICalculator的时候已经通过[ServiceContract(CallbackContract=typeof(ICallback))]指明ICallback是一个服务契约了,所以ICallback不再需要添加ServiceContractAttribute特性。
{
[OperationContract(IsOneWay = true)]//服务端不需要回调的返回值,索性将回调操作也设为单向方法。
void DisplayResult(double x, double y, double result);
}

二:实现服务

在实现了上面定义的服务契约ICalculator的服务CalculatorService中,实现了Add操作,完成运算和结果显示的工作。结果显示是通过回调的方式实现的,所以需要借助于客户端提供的回调对象(该对象在客户端调用CalculatorService的时候指定,在介绍客户端代码的实现的时候会讲到)。在WCF中,回调对象通过当前OperationContext的GetCallback<T>方法获得(T代表回调契约的类型)。

public class CalculatorService : ICalculator
{
public void Add(double x, double y)
{
double result = x + y;
ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
callback.DisplayResult(x, y, result);
}
}

注: OperationContext在WCF中是一个非常重要、也是一个十分有用的对象,它代表服务操作执行的上下文。我们可以通过静态属性Current(OperationContext.Current)得到当前的OperationContext。借助OperationContext,我们可以在服务端或者客户端获取或设置一些上下文,比如在客户端可以通过它为出栈消息(outgoing message)添加SOAP报头,以及HTTP报头(比如Cookie)等。在服务端,则可以通过OperationContex获取在客户端设置的SOAP报头和HTTP报头。关于OperationContext的详细信息,可以参阅MSDN在线文档。

三:服务寄宿

我们通过一个控制台应用程序完成对CalculatorService的寄宿工作,并将所有的服务寄宿的参数定义在配置文件中。由于双工通信依赖于一个双工的信道栈,即依赖于一个能够支持双工通信的绑定,在此我们选用了NetTcpBinding。

<system.serviceModel>
<behaviors>
<services>
<service name = "Artech.DuplexServices.Services.CalculatorService">
<endpoint address = "net.tcp://127.0.0.1:9999/CalculatorService" binding = "netTcpBinding" contract = "Artech.DuplexServices.Contracts.ICalculator"/>
</service>
</services>
</system.serviceModel>

注: 在WCF预定义绑定类型中,WSDualHttpBindingNetTcpBinding均提供了对双工通信的支持,但是两者在对双工通信的实现机制上却有本质的区别。WSDualHttpBinding是基于HTTP传输协议的;而HTTP协议本身是基于请求-回复的传输协议,基于HTTP的通道本质上都是单向的。WSDualHttpBinding实际上创建了两个通道,一个用于客户端向服务端的通信,而另一个则用于服务端到客户端的通信,从而间接地提供了双工通信的实现。而NetTcpBinding完全基于支持双工通信的TCP协议。

using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
{
host.Open();
Console.Read();
}

四:实现回调契约与服务调用

在客户端程序为回调契约提供实现,在下面的代码中CalculateCallback实现了回调契约ICallback,在DisplayResult方法中对运算结果进行输出。

class CalculateCallback : ICallback
{
public void DisplayResult(double x, double y, double result)
{
Console.WriteLine("x + y = {2} when x = {0} and y = {1}", x, y, result);
}
}

接下来实现对双工服务的调用,下面是相关的配置和托管程序。在服务调用程序中,通过DuplexChannelFactory<TChannel>创建服务代理对象,DuplexChannelFactory<TChannel>和ChannelFactory<TChannel>的功能都是一个服务代理对象的创建工厂,不过DuplexChannelFactory<TChannel>专门用于基于双工通信的服务代理的创建。在创建DuplexChannelFactory<TChannel>之前,先创建回调对象,并通过InstanceContext对回调对象进行包装。

<system.serviceModel>
<client>
<endpoint name = "CalculatorService" address = "net.tcp://127.0.0.1:9999/CalculatorService" binding = "netTcpBinding" contract = "Artech.DuplexServices.Contracts.ICalculator"/>
</client>
</system.serviceModel>
InstanceContext instanceContext = new InstanceContext(new CalculateCallback());
using (DuplexChannelFactory<ICalculator> channelFactory = new DuplexChannelFactory<ICalculator>(instanceContext, "CalculatorService"))
{
ICalculator proxy = channelFactory.CreateChannel();
using (proxy as IDisposable)
{
proxy.Add(1, 2);
Console.Read();
}
}

注意:如果采用WsDualHttpBinding,由于回调的服务监听地址采用的默认端口是80,在IIS 5.x以及之前的版本中,80端口是IIS独占的监听端口。WsDualHttpBinding定义了一个ClientBaseAddress使你能很容易地改变回调服务的基地址。对于我们给出的案例,我们只要通过下面的配置将clientBaseAddress设为可用的地址(http://127.0.0.1:8888/ CalculatorService)

< bindings >
     < wsDualHttpBinding >
         < binding name = "MyBinding" clientBaseAddress = "http://127.0.0.1:8888/calculatecallback" />
        </ wsDualHttpBinding >
  </ bindings >

WCF双通信的更多相关文章

  1. WCF入门教程五[WCF的通信模式]

    一.概述 WCF在通信过程中有三种模式:请求与答复.单向.双工通信.以下我们一一介绍. 二.请求与答复模式 描述: 客户端发送请求,然后一直等待服务端的响应(异步调用除外),期间处于假死状态,直到服务 ...

  2. 无废话WCF入门教程五[WCF的通信模式]

    一.概述 WCF在通信过程中有三种模式:请求与答复.单向.双工通信.以下我们一一介绍. 二.请求与答复模式 描述: 客户端发送请求,然后一直等待服务端的响应(异步调用除外),期间处于假死状态,直到服务 ...

  3. 【转】WCF入门教程五[WCF的通信模式]

    一.概述 WCF在通信过程中有三种模式:请求与答复.单向.双工通信.以下我们一一介绍. 二.请求与答复模式 描述: 客户端发送请求,然后一直等待服务端的响应(异步调用除外),期间处于假死状态,直到服务 ...

  4. WCF入门四[WCF的通信模式]

    一.概述 WCF的通信模式有三种:请求/响应模式.单向模式和双工通信. 二.请求/响应模式 请求/响应模式就是WCF的默认模式,前面几篇随笔中的示例都是这种模式,当客户端发送请求后(非异步状态下),即 ...

  5. 【.net 深呼吸】记录WCF的通信消息

    前面老周给大伙伴们介绍了把跟踪信息写入日志文件的方法,今天咱们换个类似的话题来扯一下,对了,咱们就说说怎么把WCF的往来消息log下来吧. 尽管在现实生活中,我们不主张偷窥他人信息,不过,偷窥程序信息 ...

  6. Wcf 双工通信的应用

    概述 双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工ME ...

  7. WCF的通信

    [ServiceContract]    public interface IContractDemoOne    {        [OperationContract(IsOneWay=true) ...

  8. WCF 双工通信

    注释:本学习是参考Artech大神的资料: 在WCF 实现双工通信 在这里我就不介绍双工通信的概念了,我写博客的目的是检测自己掌握情况,看我wcf通信后,觉得纸上得来终觉浅,绝知此事要躬行. 我使用的 ...

  9. WCF双工通信单工通信

    1.单工模式 单向通信,指通信只有一个方向进行,即从客户端流向服务,服务不会发送响应,而客户端也不会期望会有响应.这种情况下,客户端发送消息,然后继续执行 运行后报错: 2.双工模式 双工模式的特点是 ...

随机推荐

  1. selenium + python 环境配置 (一)

    超级无敌菜鸟 终于有空学习一下python 和 selenium 啦 第一步: 环境配置  (Windows版) 1. 下载安装python 根据你的电脑,下载一个python吧   这儿装的是pyt ...

  2. Openssl 加解密文件

    使用openssl 的命令行进行文件的加密与解密过程,主要有两种方式: openssl 指定加密/解密算法加密 openssl 指定公钥/私钥文件加密 openssl 指定加密/解密算法加密 To E ...

  3. [转帖]两张图看懂GDT、GDTR、LDT、LDTR的关系

    两张图看懂GDT.GDTR.LDT.LDTR的关系 2018-06-09 18:13:53 Six_666A 阅读数 2044更多 分类专栏: 深入理解linux内核   转自:http://ju.o ...

  4. [转帖]18W喂不饱有必要买30W充电器吗?iPhone 11 Pro Max充电评测

    18W喂不饱有必要买30W充电器吗?iPhone 11 Pro Max充电评测 https://www.cnbeta.com/articles/tech/895237.htm 改天买一个 设备玩一玩 ...

  5. Html大段文本自适应换行显示-SSM

    只处理前端: <style> .ctl{ table-layout:fixed } .ctl td{ word-break:break-all } </style> <d ...

  6. PPT 中用 LaTeX 插入公式、PowerPoint 中用 LaTeX 插入公式(4)

    步骤: 1. 安装 CTex 2. 安装 IguanaTex >> 下载链接1:官网 >> 下载链接2:复制链接到迅雷或IDM下载很快 3. 将「IguanaTex_v1_56 ...

  7. Neo4j查询语句总结

    最近一直在做图数据库的相关工作,对neo4j的查询语言Cypher使用较多,故在此总结记录.Cypher作为图数据库的查询语言,感觉和关系型数据库的查询语言sql差不多吧. 1.如何找到一个节点x,x ...

  8. 怎样理解window.name

    window.name表示当前窗口的名字, 而非网页的名字, 网页的名字需要使用: document.title; window.name一般是空的字符串, 他的作用其实是配合配合超链接和表单的tar ...

  9. 四、TreeSet

    HashSet 是无序的,如果要对集合实现排序,那么就需要使用TreeSet 让TreeSet 实现集合有序有两种方法 一.让元素自身具备比较排序功能,具备比较排序功能的元素只需要实现Comparab ...

  10. 【转载】salesforce 零基础开发入门学习(五)异步进程介绍与数据批处理Batchable

    salesforce 零基础开发入门学习(五)异步进程介绍与数据批处理Batchable   本篇知识参考:https://developer.salesforce.com/trailhead/for ...