20181102_WCF简单双工
- 使用管理员权限打开VS2017
2. 创建一个空白解决方案:
3. 创建几个基于.net framework的类库项目和一个基于.net Framework 的控制台项目, 然后将类库项目的class1.cs文件删除, 整体如下图:
4. 为每个类库添加对应的类文件:
a) MyWCF.WCFSimpleDuplex.Interface添加两个接口, ICalculatorService和ICallBack, 其中ICalculatorService表示要启动的服务接口, 而ICallBack表示要回调客户端时, 访问的接口
b) ICalculatorService 代码如下:
using System.ServiceModel; namespace MyWCF.WCFSimpleDuplex.Interface
{
/// <summary>
/// 定义协议的时候, 同时需要定义一个回调接口
/// 示例中定义服务契约的同时定义一个回调接口ICallBack
/// 双工中的函数不能带返回值
/// 如果你实在想要返回值, 那么自己用out
/// </summary>
[ServiceContract(CallbackContract = typeof(ICallBack))]
public interface ICalculatorService
{
/// <summary>
/// 添加isoneway属性表示, 这个函数是不是返回应答信息 ;
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
[OperationContract(IsOneWay = true)]
void Plus(int x, int y); //建立了一个Icalculator服务的协议
//这个协议带有一个回调接口ICallBack
//注意WCF的双工, 不能全靠配置, 在建立服务的时候, 就要开始处理了
}
}
c) ICallBack代码如下
using System.ServiceModel; namespace MyWCF.WCFSimpleDuplex.Interface
{
/// <summary>
/// 不需要协议, 因为它不是一个服务契约, 它只是一个约束,这个约束由客户端实现
/// </summary>
public interface ICallBack
{
/// <summary>
/// 这里就是回调的时候完成的函数, 这个接口也要加上Isoneway=true
/// </summary>
/// <param name="m"></param>
/// <param name="n"></param>
/// <param name="result"></param>
[OperationContract(IsOneWay = true)]
void Show(int m, int n, int result);
} //要发布一个双工协议 ,首先在服务的建立WCF服务, 服务的契约上面指定callbackContract回调的类型
//建立回调接口, 回调接口就是等下要执行的接口
}
5. 接下来处理 MyWCF.WCFSimpleDuplex.Model 的代码, 它就一个类:
using System.Runtime.Serialization; namespace MyWCF.WCFSimpleDuplex.Model
{
[DataContract]
public class WCFUser
{
//[DataMember]
public int Id { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public int Sex { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
} public enum WCFUserSex
{
Famale,
Male,
Other
}
}
6. 关于服务类MyWCF.WCFSimpleDuplex.Service的处理如下:
using System.ServiceModel;
using MyWCF.WCFSimpleDuplex.Interface; namespace MyWCF.WCFSimpleDuplex.Service
{
/// <summary>
/// 对ICalculatorService的一个实现类; 实现的时候, 除了要完成自己的计算, 还要完成, 对接口的回调
/// </summary>
public class CalculatorService : ICalculatorService
{
/// <summary>
/// 完成计算,然后去回调
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
public void Plus(int x, int y)
{
int result = x + y;
System.Threading.Thread.Sleep(3000); //OperationContext表示当前操作的上下文
//OperationContext.Current.GetCallbackChannel<ICallBack>();这里有点像IOC, 给你一个接口然后生成一个实例; 注意哦, 这里的ICallBack还有没有任何实现, 而这个实现是在客户端(client)处去完成的
ICallBack callBack =OperationContext.Current.GetCallbackChannel<ICallBack>();
callBack.Show(x, y, result);
}
}
}
7. 接下来是控制台MyWCF.WCFSimpleDuplex.ConsoleTest的代码实现, 首先是他的配置文件
a) 初始时的配置文件如下图:
b) 在configuration节点添加如下配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup> <system.serviceModel> <!--WCF的配置文件 , WCF的配置文件一个是基于TCP的, 一个是基于http的; 可以添加多个; 如果添加多个就是下面的配置格式 -->
<behaviors>
<serviceBehaviors>
<!--<behavior name="MathServicebehavior"> --><!--这里配置第一个Behavior的节点--><!--
<serviceDebug httpHelpPageEnabled="false"/>
<serviceMetadata httpGetEnabled="false"/>
<serviceTimeouts transactionTimeout="00:10:00"/>
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000"/>
</behavior>-->
<behavior name="CalculatorServicebehavior"> <!--这里配置第二个Behavior的节点-->
<serviceDebug httpHelpPageEnabled="false"/>
<serviceMetadata httpGetEnabled="false"/>
<serviceTimeouts transactionTimeout="00:10:00"/>
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000"/>
</behavior>
</serviceBehaviors>
</behaviors>
<!--在tcp中上面几行和http的配置都是一样的-->
<bindings>
<netTcpBinding>
<binding name="tcpbinding"> <!--指定为tcp的协议类型-->
<security mode="None">
<!--clientCredentialType="None" → 表示加密类型 protectionLevel="None" 表示安全级别-->
<transport clientCredentialType="None" protectionLevel="None"/>
</security>
</binding>
</netTcpBinding>
</bindings> <services>
<service name="MyWCF.WCFSimpleDuplex.Service.CalculatorService" behaviorConfiguration="CalculatorServicebehavior">
<host> <!--这里配置第一个服务的名称和服务的具体指向类-->
<baseAddresses>
<add baseAddress="net.tcp://localhost:9999/CalculatorService"/><!--指定的协议为net tcp协议-->
</baseAddresses>
</host>
<endpoint address="" binding="netTcpBinding" bindingConfiguration="tcpbinding" contract="MyWCF.WCFSimpleDuplex.Interface.ICalculatorService"/>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
<!--<service name="MyWCF.WCFSimpleDuplex.Service.MathService" behaviorConfiguration="MathServicebehavior">
<host>--><!--这里配置第二个服务的名称和服务的具体指向类--><!--
<baseAddresses>
<add baseAddress="net.tcp://localhost:9999/MathService"/>
</baseAddresses>
</host>
<endpoint address="" binding="netTcpBinding" bindingConfiguration="tcpbinding" contract="MyWCF.WCFSimpleDuplex.Interface.IMathService"/>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>-->
</services>
</system.serviceModel>
</configuration>
c) Program代码如下:
using System;
using System.ServiceModel;
using MyWCF.WCFSimpleDuplex.Service; namespace MyWCF.WCFSimpleDuplex.ConsoleTest
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("开始挂起服务");
ServiceInit.Process();
}
catch (Exception ex)//如果报无法注册. . ., 则说明需要管理员权限, 启动这个程序
{
//服务“SOA.WCF.Service.CalculatorService”有零个应用程序(非基础结构)终结点。这可能是因为未找到应用程序的配置文件,或者在配置文件中未找到与服务名称匹配的服务元素,或者服务元素中未定义终结点。
//没有配置文件 //另一应用程序已使用 HTTP.SYS 注册了该 URL。
//端口 9999 被其它应用程序占用了, 找到并将其停止
Console.WriteLine(ex.Message);
}
Console.Read();
}
} /// <summary>
/// WCF寄宿到控制台
/// </summary>
public class ServiceInit
{
public static void Process()
{
//ServiceHost →表示提供服务的主机,使用服务的类型及其指定的基址初始化 System.ServiceModel.ServiceHost 类的新实例。
Type type = typeof(CalculatorService);
ServiceHost host = new ServiceHost(type); host.Opening += (s, e) => Console.WriteLine($"{type} 准备打开");
//已经打开事件
host.Opened += (s, e) => Console.WriteLine($"{type} 已经正常打开"); //开启服务; 注意当这里需要Open的时候, 会去配置文件中检查是否有配置了MathService这个类的behavior(行为)
host.Open(); Console.WriteLine("输入任何字符,就停止");
Console.Read();
host.Close();
Console.Read();
} } }
8. 完成以上步骤就可以启动试试看了:
9. 可以使用 cmd 命令 netstat -ano | find "9999", 查看下端口9999是否被监听
10. 双工的服务端已经处理完毕, 接下来开始处理客户端, 当然客户端首先就要对刚才的ICallBack进行实现, 这个毋容置疑的
11. 再新打开一个VS2017, 创建一个控制台测试项目:
12. 接下来不用多想, 第一件事, 添加服务引用, 第二件事实现服务端的那个ICallBack接口
a) 添加服务引用
b) 实现ICallBack接口, 注意这个类里的Show 方法, 在客户端没有任何代码调用
using System; namespace MyWCF.WCFSimpleDuplexConsoleTest.CTest
{
/// <summary>
/// 具体实现的回调
/// </summary>
public class CallBackService : MyDuplexConsoleTest.ICalculatorServiceCallback
{
public void Show(int m, int n, int result)
{ Console.WriteLine($"回调操作展示, 这个操作发生在两秒之后:{m}+{n}={result}");
}
}
}
c) 整体client截图:
13. 然后在program中的代码, 建议单步调试看看代码的运行过程:
using System;
using System.ServiceModel; namespace MyWCF.WCFSimpleDuplexConsoleTest.CTest
{
class Program
{
static void Main(string[] args)
{
MyDuplexConsoleTest.CalculatorServiceClient client = null;
try
{
Console.WriteLine("客户端来测试双工!~~"); //创建一个需要回调的实例, 等会服务端进行回调的
InstanceContext context = new InstanceContext(new CallBackService()); client = new MyDuplexConsoleTest.CalculatorServiceClient(context);
client.Plus(123, 234);
client.Close();
}
catch (Exception ex)
{
if (client != null)
client.Abort();
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
}
14. 结果截图
15. 结束
20181102_WCF简单双工的更多相关文章
- 一种简单的CQRS架构设计及其实现
一.为什么要实践领域驱动? 近一年时间我一直在思考一个问题:"如何设计一个松耦合.高伸缩性.易于维护的架构?".之所以有这样的想法是因为我接触的不少项目都是以数据库脚本来实现业务逻 ...
- WCF学习之旅—HTTP双工模式(二十)
WCF学习之旅—请求与答复模式和单向模式(十九) 四.HTTP双工模式 双工模式建立在上文所实现的两种模式的基础之上,实现客户端与服务端相互调用:前面介绍的两种方法只是在客户端调用服务端的方法,然后服 ...
- 利用WCF的双工通讯实现一个简单的心跳监控系统
何为心跳监控系统? 故名思义,就是监控某个或某些个程序的运行状态,就好比医院里面的心跳监视仪一样,能够随时显示病人的心跳情况. 心跳监控的目的是什么? 与医院里面的心跳监视仪目的类似,监控程序运行状态 ...
- 利用WCF双工模式实现即时通讯
概述 WCF陆陆续续也用过多次,但每次都是浅尝辄止,以将够解决问题为王道,这几天稍闲,特寻了些资料看,昨晚尝试使用WCF的双工模式实现了一个简单的即时通讯程序,通过服务端转发实现客户端之间的通讯.这只 ...
- WCF双工通讯以及客户端间的间接通讯
由于学习计划安排不当,对WCF的认知一直停滞不前,最近工作上又用回了WCF,重拾一下,看到蒋老师介绍双工通讯的博文,实践一下,积累一下.原想着WCF的双工通讯就是原本的客户端能调用服务端的方法之余,服 ...
- Wcf 双工通信的应用
概述 双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工ME ...
- 利用WCF的双工通讯实现一个简单的心跳监控系统 z
利用WCF的双工通讯实现一个简单的心跳监控系统 http://www.cnblogs.com/zuowj/p/5761011.html 何为心跳监控系统? 故名思义,就是监控某个或某些个程序的运行状态 ...
- SMTP 简单邮件传输协议
SMTP 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传 ...
- [转载]WCF实现双工通信
双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...
随机推荐
- 利用JS获取地址栏的中文参数
地址栏中为:localhost:22865/ZYHSYY.aspx?BQH=305&DoctorName=张三&DoctorId=100我想利用JS获取到“张三”,请问该如何写js?目 ...
- php超级全局变量和魔术变量
php超级全局变量和魔术变量 一.总结 一句话总结: 1.两者的书写形式非常不一样,超级全局变量是$_大写变量名 的形式,魔术变量是 __大写变量名的形式__ 2.两者的应用范围不一样,超级全局变量是 ...
- 找出此产品描述中包含N个关键字的长度最短的子串
阿里巴巴笔试题:给定一段产品的英文描述,包含M个英文字母,每个英文单词以空格分隔,无其他标点符号:再给定N个英文关键词,请说明思路并变成实现方法. String extractSummary(Stri ...
- MySQL5.7版本开启二进制日志是log_bin、bin-log 还是 bin_log ?
已Mac系统为例,文件:/usr/local/mysql/support-files/my-default.cnf 是mysql的默认配置文件,你可以直接修改这个文件但是不推荐,你可以在/etc/my ...
- yii2:oracle date类型字段的写入或查询
insert: insert into tabname(datecol) value(sysdate) ; -- 用date值 insert into tabname(datecol) value(s ...
- Binary Differences
https://csacademy.com/contest/archive/task/binary-differences n个数,只有0和1,求所有子区间价值不相同的有多少中,价值是0的个数-1的个 ...
- Linux常用的50个命令
50个最常用的Unix/Linux命令 2014-08-20 这篇文章翻译自http://www.thegeekstuff.com/2010/11/50-linux-commands/这些都是一些很常 ...
- language model ——tensorflow 之RNN
代码结构 tf的代码看多了之后就知道其实官方代码的这个结构并不好: graph的构建和训练部分放在了一个文件中,至少也应该分开成model.py和train.py两个文件,model.py中只有一个P ...
- MVC框架中的值提供机制(一)
在MVC框架中action方法中的Model数据的绑定的来源有很多个,可能是http请求中的get参数或是post提交的表单数据,会是json字符串或是路径中的相关数据;MVC框架中针对这些不同的数据 ...
- 【辅助工具】Python实现微信跳一跳
最近迷上了微信跳一跳小游戏,正好也看到知乎上有大神分享了技术贴,我也参考了好多资料,原理就是通过abd命令截取图片,python计算两个点距离,然后转化按压时间,让电脑来完成游戏.我花了很长时间才把程 ...