1. 使用管理员权限打开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简单双工的更多相关文章

  1. 一种简单的CQRS架构设计及其实现

    一.为什么要实践领域驱动? 近一年时间我一直在思考一个问题:"如何设计一个松耦合.高伸缩性.易于维护的架构?".之所以有这样的想法是因为我接触的不少项目都是以数据库脚本来实现业务逻 ...

  2. WCF学习之旅—HTTP双工模式(二十)

    WCF学习之旅—请求与答复模式和单向模式(十九) 四.HTTP双工模式 双工模式建立在上文所实现的两种模式的基础之上,实现客户端与服务端相互调用:前面介绍的两种方法只是在客户端调用服务端的方法,然后服 ...

  3. 利用WCF的双工通讯实现一个简单的心跳监控系统

    何为心跳监控系统? 故名思义,就是监控某个或某些个程序的运行状态,就好比医院里面的心跳监视仪一样,能够随时显示病人的心跳情况. 心跳监控的目的是什么? 与医院里面的心跳监视仪目的类似,监控程序运行状态 ...

  4. 利用WCF双工模式实现即时通讯

    概述 WCF陆陆续续也用过多次,但每次都是浅尝辄止,以将够解决问题为王道,这几天稍闲,特寻了些资料看,昨晚尝试使用WCF的双工模式实现了一个简单的即时通讯程序,通过服务端转发实现客户端之间的通讯.这只 ...

  5. WCF双工通讯以及客户端间的间接通讯

    由于学习计划安排不当,对WCF的认知一直停滞不前,最近工作上又用回了WCF,重拾一下,看到蒋老师介绍双工通讯的博文,实践一下,积累一下.原想着WCF的双工通讯就是原本的客户端能调用服务端的方法之余,服 ...

  6. Wcf 双工通信的应用

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

  7. 利用WCF的双工通讯实现一个简单的心跳监控系统 z

    利用WCF的双工通讯实现一个简单的心跳监控系统 http://www.cnblogs.com/zuowj/p/5761011.html 何为心跳监控系统? 故名思义,就是监控某个或某些个程序的运行状态 ...

  8. SMTP 简单邮件传输协议

    SMTP 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传 ...

  9. [转载]WCF实现双工通信

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

随机推荐

  1. 在mybatis中使用存储过程报错java.sql.SQLException: ORA-06550: 第 1 行, 第 7 列: PLS-00905: 对象 USER1.HELLO_TEST 无效 ORA-06550: 第 1 行, 第 7 列:

    hello_test是我的存储过程的名字,在mapper.xml文件中是这么写的 <select id="getPageByProcedure" statementType= ...

  2. HDU 4725 建图

    http://acm.hdu.edu.cn/showproblem.php?pid=4725 The Shortest Path in Nya Graph Time Limit: 2000/1000 ...

  3. 常见GAN的应用

    深入浅出 GAN·原理篇文字版(完整)|干货 from:http://baijiahao.baidu.com/s?id=1568663805038898&wfr=spider&for= ...

  4. Database项目中关于Procedure sp_refreshsqlmodule_internal的错误

    最近项目中发现一怪问题,使用DB项目发布数据库时,总提示 “(110,1): SQL72014: .Net SqlClient Data Provider: Msg 1222, Level 16, S ...

  5. Java并发编程之CountDownLatch

    一.场景描述 在多线程程序设计中,经常会遇到一个线程等待一个或多个线程的场景 例如:百米赛跑,十名运动员同时起跑,由于速度的快慢,肯定有先到达和后到达的,而终点有个统计成绩的仪器,当所有选手到达终点时 ...

  6. angualr4 环境搭建

    不得不说现在很流行前端MVC框架,angularjs算是一种.以前也用过angularjs感觉还不错,刷新了我对前端的认知.特别是因为我本身是个java开发.但是感觉还是有很多缺点的,直到angula ...

  7. spring 和springmvc 在 web.xml中的配置

    (1)问题:如何在Web项目中配置Spring的IoC容器? 答:如果需要在Web项目中使用Spring的IoC容器,可以在Web项目配置文件web.xml中做出如下配置: <!-- Sprin ...

  8. Discuz代码研究-编码规范

    Discuz中的编码规范很值得PHP开发人员借鉴.里面既介绍了编码时代码标记,注释,书写规则,命名原则等方面基础的内容,对代码的安全性,性能,兼容性,代码重用,数据库设计,数据库性能及优化作了阐述,这 ...

  9. VS2010中使用 SpecFlow + Selenium.WebDriver

    安装(VS扩展.程序包) [工具]->[扩展管理器],安装SpecFlow [工具]->[库程序包管理]->[程序包管理器控制台] PM> Install-Package Sp ...

  10. poj 3517

    题目链接  http://poj.org/problem?id=3517 题意        约瑟夫环  要求最后删掉的那个人是谁: 方法        理解递推公式就行了  考虑这样一组数据  k ...