博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在wcf中实现双工通信
阅读量:4710 次
发布时间:2019-06-10

本文共 3610 字,大约阅读时间需要 12 分钟。

 
读wcf全面解析之笔记
如果按照双工模式(Duplex)进行消息交换,则已意味着参与消息交换的双方都能勾向对方发送消息,双工通信不仅仅使服务回调客户端成为可能,还可以帮助我们实现基于发布-订阅的方式进行通信。

服务回调客户端:
客户端在进行服务调用的时候,附加上一个回调对象。服务在执行服务操作的过程中,通过回调这个对象来回调客户端的操作。
发布-订阅的方式:其实是一中双工模式的典型变体,这个有点类似在C#中的委托和事件、也有点类似设计模式中的观察者模式。
具体的就是说若干的订阅者就某个主题向发布者申请订阅,发布者将所有订阅者保存在一个订阅者列表,在某个时刻将主体发送给该主题的订阅者。

接下来通过一个简单的实例来演示回调在wcf中的应用
1.建一个空的解决方案,然后添加4个项目:
①Client控制台应用程序,最为客户端来显示回调结果
②ServerHosting控制台应用程序,服务的宿主程序,用来寄宿服务的。
③Services类库,用来创建服务。
④Contracts类库,用来创建服务契约
2.建立完成之后开始来定义契约
①在Contracts项目上建立一个契约接口ICalculator,通过回调方式在客户端输出运算结果,所以Add并无返回值。
using System.ServiceModel;[ServiceContract(Namespace="http://www.lordbaby.com",        CallbackContract=typeof(ICalculatorCallback))]    public interface ICalculator    {        [OperationContract]        void Add(double x,double y);    }
服务对客户端进行回调相当于调用寄宿于客户端的"回调服务",所以需要确定回调的服务契约,这个契约通过应用在契约接口ServiceContractAttribute特性的CallbackContract属性来指定。然后就是回调契约的接口定义如下:
using System.ServiceModel;public interface ICalculatorCallback    {        [OperationContract]        void DisplayResult(double result, double x, double y);    }
②在Services项目中建立实现了契约接口ICalculator的服务CalculatorService,定义如下
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]    public class CalculatorService:ICalculator    {        public void Add(double x, double y)        {            double result = x + y;            ICalculatorCallback callback = OperationContext.Current.GetCallbackChannel
(); callback.DisplayResult(result, x, y); } }
通过当前服务操作的上下文调用GetCallbackChannel<T>(T为回调契约类型)得到用于调用回调服务的对象,最终通过回调代理的DisplayResult
注:
OperationContext是wcf十分重要的对象,它代表服务操作执行的上下文,可以通过
OperationContext.Current来得到当前的
OperationContext,
比如在客户端可以通过它为出栈消息(outgoing message)添加SOAP报头,以及HTTP报头(比如Cookie)等。在服务端,则可以通过OperationContex获取在客户端设置的SOAP报头和HTTP报头。关于OperationContext的详细信息.
③在Client项目中定义实现可回调契约的“回调服务”来显示元算结果
public class CalculatorCallbackService:ICalculatorCallback    {        public void DisplayResult(double result, double x, double y)        {            Console.WriteLine("x+y={2} when x={0},y={1}",x,y,result);        }    }
然后建立一个客户端配置文件:
④在ServiceHosing项目中寄宿服务
class Program    {        static void Main(string[] args)        {            using (ServiceHost host=new ServiceHost (typeof(CalculatorService)))            {                host.Open();                Console.WriteLine("Calculator已经启动,按任意键结束");                Console.Read();            }        }    }
然后建立一个服务端配置文件
⑤在Client中回调服务
static void Main(string[] args)        {            InstanceContext instanceContext = new InstanceContext(new CalculatorCallbackService());            using (DuplexChannelFactory
channelFactory = new DuplexChannelFactory
(instanceContext, "calculatorservice")) { ICalculator proxy = channelFactory.CreateChannel(); using (proxy as IDisposable) { proxy.Add(1, 2); Console.Read(); } } }
注意:1.服务代理工厂换成了DuplexChannelFactory<TChannel>
2.调用之前需要指定一个用于封装回调对象的InstanceContext
好了现在可以运行程序,分别用2个vs打开解决方案,首先设ServiceHosting项目启动项目,运行
然后在另一个vs中设Client为启动项目,运行,输出结果:
        
注:如果没有在Services项目中的CalculatorService中
源码:

转载于:https://www.cnblogs.com/hailiang2013/archive/2012/06/26/2846421.html

你可能感兴趣的文章
源码编译安装php
查看>>
切换用户,显示用户名, 调用Windows系统命令
查看>>
修改dede标题长度限制&nbsp;改此参数后…
查看>>
ubuntu下安装Docker
查看>>
mysql的字符编码
查看>>
《编程之美》读书笔记 -- 1.4买书问题
查看>>
稳定排序
查看>>
libev & libevent简介
查看>>
ProtoBuffer优势
查看>>
@Repository、@Service、@Controller 和 @Component
查看>>
bootstrap-wysihtml5设置值
查看>>
Windows常用快捷键与常用命令
查看>>
290. Word Pattern 单词匹配模式
查看>>
project1
查看>>
const char*, char const*, char*const的区别
查看>>
vue踩坑记-在项目中安装依赖模块npm install报错
查看>>
mySQL优化, my.ini 配置说明
查看>>
mysql系统数据库
查看>>
alwayson监控
查看>>
浅谈 js 函数调用
查看>>