WCF入门四[WCF的通信模式]
一、概述
WCF的通信模式有三种:请求/响应模式、单向模式和双工通信。
二、请求/响应模式
请求/响应模式就是WCF的默认模式,前面几篇随笔中的示例都是这种模式,当客户端发送请求后(非异步状态下),即使返回的是void客户端会一直等待服务端的响应后才继续下面的操作。
优点:可以及时的向客户端返回错误信息。
缺点:面对服务端需要长时间处理的情况下,降低客户端的响应速度和性能。
这个大家都好理解,就不再复述。
三、单向模式
单向模式和请求/响应模式相反,单向模式就是客户端发送请求后直接进行接下来的操作,不会等待服务端的响应,并且服务端也不会发送响应。所以单向模式的方法不得声明输出参数、返回值和引用参数。
单向模式的需要在OpertaionContract中设置IsOneWay=true ,如下所示:
[OperationContract(IsOneWay = true)]
void ShowDay(string day);
优点:客户端反应速度快、性能强,当然排除需要超大量传输参数的情况。
缺点:不能及时获取服务端是否操作结果。
四、双工通信
双工通信就是实现客户端和服务端方法可以相互调用。一般情况下都是客户端调用服务端的方法,但是双工通信可以让服务端调用客户端的方法。双工通信时建立在上述两种方式之上的,并不是相互冲突的。
1.服务端
定义服务契约和回调契约,服务契约必须通过特性[ServiceContract(CallbackContract = typeof(ICustomCallback))]来关联回调契约,回调契约不必声明ServiceContract特性,但是方法必须声明OperationContract否则在客户端引用服务后无法使用该方法,这里我们用单向模式。
namespace WcfServiceLibrary
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IDay”。
[ServiceContract(CallbackContract = typeof(ICustomCallback))]
public interface IDay
{
[OperationContract]
string ShowDay(int day);
}
public interface ICustomCallback
{
[OperationContract(IsOneWay=true)]
void UserCustomMethod(string str);
}
}
在配置文件中binding指定WSDualHttpBinding,支持回调的绑定有4种:WSDualHttpBinding、NetTcpBinding、NetNamedPipeBinding、NetPeerTcpBinding,我这里用第一种。
<endpoint address="" binding="wsDualHttpBinding" contract="WcfServiceLibrary.IDay">
实现服务契约接口,不需要实现回调契约的接口,因为回调是使用客户端的方法所以在客户端实现。OperationContext是WCF中非常重要的对象,它表示操作执行的上下文,通过OperationContext的方法GetCallbackChannel<T>()来获取回调对象后使用回调方法。
namespace WcfServiceLibrary
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“Day”。
public class Day : IDay
{
ICustomCallback customCallback = null;
public Day()
{
customCallback = OperationContext.Current.GetCallbackChannel<ICustomCallback>();
}
public string ShowDay(int day)
{
customCallback.UserCustomMethod("哈哈哈哈");//使用回调方法
return string.Format("WCF服务返回Day是:{0}", day);
}
}
}
2.客户端
客户端引用WCF服务后会在Service References文件加下生成一个服务类,里面定义了回调接口IDayCallback如下:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface IDayCallback { [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://tempuri.org/IDay/UserCustomMethod")]
void UserCustomMethod(string str);
}
实现回调方法,并调用WCF服务:
class Program
{
static void Main(string[] args)
{
InstanceContext instanceContext = new InstanceContext(new CustomCallback());
DayClient client = new DayClient(instanceContext);
Console.WriteLine(client.ShowDay());
Console.ReadLine();
}
}
public class CustomCallback : IDayCallback
{
public void UserCustomMethod(string str)
{
Console.WriteLine("这是客户端方法:{0}",str);
}
}
调试可以看到,在服务端成功调用了客户端的方法UserCustomMethod(string str):
五、回调死锁
由于双工通信下客户端和服务端可以互相调用对方的方法,所以会出现双方都等待对方响应的情况,而造成死锁而报错。上面的例子没有造成死锁是因为使用了单向模式,不需要等待响应。那么如果需要使用带有返回值的回调方法那该怎么办呢?
我们将上述服务端回调契约定义的回调方法改为string UserCustomMethod(string str)并去掉IsOneWay = true,然后在服务端进行以下改造:
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“Day”。
public class Day : IDay
{
ICustomCallback customCallback = null;
public Day()
{
customCallback = OperationContext.Current.GetCallbackChannel<ICustomCallback>();
}
public string ShowDay(int day)
{
string str = customCallback.UserCustomMethod("哈哈哈哈");
return string.Format("WCF服务返回Day是:{0}。{1}", day, str);
}
}
之后在客户端更新服务,运行报以下错误:
很明显服务不支持并发,由于等待响应而产生了死锁。可以修改ServiceBehavior特性中的ConcurrencyMode就可以了。那么我们修改下代码如下,ServiceBehavior只能声明类:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class Day : IDay
{
ICustomCallback customCallback = null;
public Day()
{
customCallback = OperationContext.Current.GetCallbackChannel<ICustomCallback>();
}
public string ShowDay(int day)
{
string str = customCallback.UserCustomMethod("哈哈哈哈");
return string.Format("WCF服务返回Day是:{0}。{1}", day, str);
}
}
再次运行客户端就成功啦:
六、说明
这个随笔是我自己学习流程的一个记录,和大家共勉。
WCF入门四[WCF的通信模式]的更多相关文章
- [老老实实学WCF] 第十篇 消息通信模式(下) 双工
老老实实学WCF 第十篇 消息通信模式(下) 双工 在前一篇的学习中,我们了解了单向和请求/应答这两种消息通信模式.我们知道可以通过配置操作协定的IsOneWay属性来改变模式.在这一篇中我们来研究双 ...
- [老老实实学WCF] 第四篇 初探通信--ChannelFactory
老老实实学WCF 第四篇 初探通信--ChannelFactory 通过前几篇的学习,我们简单了解了WCF的服务端-客户端模型,可以建立一个简单的WCF通信程序,并且可以把我们的服务寄宿在IIS中了. ...
- WCF入门三[WCF宿主]
一.概述 WCF程序必须在宿主上运行,也就是WCF服务必须寄宿在某一个windows的进程中,可以是IIS.控制台程序.窗体程序.WAS以及所有.net程序等程序进程中.在我用VS2013创建WCF服 ...
- (转)[老老实实学WCF] 第四篇 初探通信--ChannelFactory
第四篇 初探通信--ChannelFactory 通过前几篇的学习,我们简单了解了WCF的服务端-客户端模型,可以建立一个简单的WCF通信程序,并且可以把我们的服务寄宿在IIS中了.我们不禁感叹WCF ...
- WCF入门一[WCF概述]
一.什么是WCF WCF是使用托管代码建立和运行面向服务(Service Oriented)应用程序的统一框架.它使得开发者能够建立一个跨平台的.安全.可信赖.事务性的解决方案,且能与已有系统兼容协作 ...
- gRPC(2):四种基本通信模式
在 gRPC(1):入门及简单使用(go) 中,我们实现了一个简单的 gRPC 应用程序,其中双方通信是简单的请求-响应模式,没发出一个请求都会得到一个响应,然而,借助 gRPC 可以实现不同的通信模 ...
- WCF入门教程[WCF基本应用]
一.概述 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分.由 .NE ...
- WCF入门二[WCF的配置文件]
一.概述 往往在很多项目中数据库连接字符串.变量和一些动态的加载类会写在配置文件中.WCF也会在配置文件中写入一些配置参数,比如服务的地址.服务用于发送和接收消息的传输和消息编码等,通过配置文件可以灵 ...
- 纯手写wcf代码,wcf入门,wcf基础教程
1.定义服务协定 =>定义接口 using System.ServiceModel; namespace WcfConsole { /// <summary> /// 定义服 ...
随机推荐
- NEUACM1132: Renew MST Quickly 增量最小生成树
题目链接:http://acm.neu.edu.cn/hustoj/problem.php?id=1132 和UVa11354很类似 题意: 原先有一棵树,每次加一条边,看最小生成树大小: 这个和增量 ...
- httpServeltRequest和Model传值的区别
需要将请求发过来的数据(或者说参数)传递到重定向的页面/转发的页面的时候,就要用到>>model.addAttribute("mine", UserUtils.getC ...
- ACM-ICPC 2018 徐州赛区网络预赛 A.Hard to prepare 【规律递推】
任意门:https://nanti.jisuanke.com/t/31453 A.Hard to prepare After Incident, a feast is usually held in ...
- mac下配置Node.js开发环境、express安装、创建项目
mac下配置Node.js开发环境.express安装.创建项目 一.node.js的安装 去官网下载对应的平台版本就可以了,https://nodejs.org 二.express安装 sudo n ...
- 【办公-Word-VB】人民币大写转换-带完整注释
完整代码见:我的CSDN博客 -------------------- 应公司财务人员的请求,需在Word中做个:输入阿拉伯数字,自动转换成大写,并填充到Word控件中对应的亿.万.千控件格子的功能, ...
- android 多线程 异步消息处理 服务 学习笔记 (六)
三种多线程编程方法 1 class Mythread extends Thread{ @Override public void run(){} } new Mythread().start() 2 ...
- vue 修改框架less变量
以vant框架为例,vue项目以less作为css处理器: less/var-reset.less @import '~vant/lib/index.less'; // Color variables ...
- SpringBoot非官方教程 | 第二十二篇: 创建含有多module的springboot工程
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springbot22-modules/ 本文出自方志朋的博客 这篇文 ...
- Flask—05-理解掌握flask数据模型(01)
数据模型 数据库回顾 分类: 关系型数据库:MySQL.sqlite.… 非关系型数据库:Redis.MongoDB.… 操作: 执行原生SQL语句,每次都需要拼接SQL语句,非常繁琐而且特别容易出错 ...
- java之递归学习
递归思想(2018-10-22): 递归就是方法里调用自身 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口 递归算法代码显得很简洁,但递归算法解题的运行效率较低.所以不提倡用递归设计程序 ...