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又具 ...
随机推荐
- C# 捕获数据库自定义异常
在 SQL Server 的存储过程中根据业务逻辑的要求,有时需要抛出自定义异常,由C#程序俘获之并进行相应的处理.SQL Server 抛出自定义异常和简单,像这样就可以了:RAISERROR('R ...
- spring4x,暂时停更
spring4x,暂时停更 鄙人愚笨,没有spring基础,直接上了spring4x,发现无法理解(另外spring4x实战课本演示不详,本人学识有限),现从spring3开始.
- 【转】安装OS X虚拟机错误vcpu-0:VERIFY vmcore/vmm/main/physMem_monitor.c:1123
新建一个虚拟机, 选择客户机操作系统为Apple MacOS X 10.10, 其余参数可以默认. 注意建好之后不要急着打开客户机, 因为直接打开你会发现新建的客户机将会无法启动. 仔细阅读Mac O ...
- 【专题】区间dp
1.[nyoj737]石子合并 传送门:点击打开链接 描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这 ...
- eclipse配置及常用快捷键
1. eclipse查看一个方法被谁引用(调用)的快捷键四种方式 1.(首推)双击选中该方法,Ctrl+Alt+H 如果你想知道一个类的方法到底被那些其他的类调用,那么请选中这个方法名,然后按“Ct ...
- objective-c和java下解析对象类型和数组类型JSON字符串
首先讲objective-c如何实现: 这里需要用到2个插件,一个是JSONKit,另一个是Jastor,一共包含6个文件,3个.h头文件和3个.m实现文件.在ARC的工程中如何导入不支持ARC的第三 ...
- 深入解析Glide源码
Glide 是 Google的开源项目, Glide具有获取.解码和展示视频剧照.图片.动画等功能,它还有灵活的API,这些API使开发者能够将Glide应用在几乎任何网络协议栈里.创建Glide的主 ...
- Flash Builder 4.6配置ASDoc
ASDoc是Adobe自带的文档生成工具.可以生成类似JavaDoc格式的文档. 关于ASDoc详情参见官方文档: http://help.adobe.com/zh_CN/flex/using/WSd ...
- animal farm 第一章阅读笔记
chapter 1 Old Major's dream. paragraph 1 //Mr Jones is the mastor of the Manor Farm.That night ...
- Java [Leetcode 347]Top K Frequent Elements
题目描述: Given a non-empty array of integers, return the k most frequent elements. For example,Given [1 ...