一、

在前一章中主要介绍了服务端的监听地址与逻辑地址。本节模拟消息转发机制来实际体验一把终结点的监听地址是如何使用的。

先下载一个叫做TcpTrace的小软件(108k),它能够截取端口消息,并转发消息。

先来看看服务端代码,服务端的绑定使用WS2007HttpBinding的不加密模式,因为我们等会还要看TcpTrace捕获的数据明文,所以不能加密。客户端也是使用不加密的WS2007HttpBinding。

  1. using System.ServiceModel;
  2. using System.ServiceModel.Description;
  3. using System.ServiceModel.Channels;
  4. namespace host
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. using (ServiceHost host = new ServiceHost(typeof(mywcf.Calculator)))
  11. {
  12. WS2007HttpBinding bind = new WS2007HttpBinding();
  13. WSHttpSecurity security = new WSHttpSecurity();
  14. security.Mode = SecurityMode.None;
  15. bind.Security = security;
  16. host.AddServiceEndpoint(typeof(mywcf.ICalculator), bind, "http://localhost:8888");
  17. host.Opened += delegate { Console.WriteLine("Service Start!"); };
  18. host.Open();
  19. Console.ReadLine();
  20. }
  21. }
  22. }
  23. }

服务端发布一个终结点。由前一章说道,默认逻辑地址与监听地址一致,都是http://localhost:8888。

客户端代码如下:

  1. using System.ServiceModel;
  2. using System.ServiceModel.Description;
  3. using System.ServiceModel.Channels;
  4. namespace client
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. WS2007HttpBinding bind = new WS2007HttpBinding();
  11. WSHttpSecurity security = new WSHttpSecurity();
  12. security.Mode = SecurityMode.None;
  13. bind.Security = security;
  14. EndpointAddress endpint=new EndpointAddress("http://localhost:8888");
  15. mywcf.ICalculator client = ChannelFactory<mywcf.ICalculator>.CreateChannel(bind, endpint, new Uri("http://localhost:9999"));
  16. Console.WriteLine(client.Add(1, 2));
  17. }
  18. }
  19. }

先启动服务端,再启动客户端。客户端报了一个错误,无法找到正确的终结点。

客户端的访问的逻辑地址为http://localhost:8888,监听地址为http://localhost:9999。但是服务端监听的是8888,并没有监听9999,所以访问失败。我们现在利用TcpTrace工具,把服务端9999端口收到的消息转发至服务端8888端口,服务端就能够正确的接收到请求。

点击OK,现在再次先后启动服务端和客户端,访问成功,并且已经成功转发。

现在分析一下消息内容。客户端请求<To>报头为逻辑地址为localhost:8888,目标地址为localhost:9999,<Body>为x=1,y=2,请求Add操作。下面服务端返回成功,<AddResult>为3。正因为客户端的<To>逻辑地址与服务端的逻辑地址一致,才可以通过终结点的消息筛选器。

二、

若服务端代码不变,服务端的逻辑地址和监听地址依然是8888,现在将客户端的逻辑地址和监听地址都设置为9999,再通过TcpTrace转发,将9999端口消息转发到8888端口。

客户端代码如下:

  1. using System.ServiceModel;
  2. using System.ServiceModel.Description;
  3. using System.ServiceModel.Channels;
  4. namespace client
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. WS2007HttpBinding bind = new WS2007HttpBinding();
  11. WSHttpSecurity security = new WSHttpSecurity();
  12. security.Mode = SecurityMode.None;
  13. bind.Security = security;
  14. EndpointAddress endpint=new EndpointAddress("http://localhost:9999");
  15. mywcf.ICalculator client = ChannelFactory<mywcf.ICalculator>.CreateChannel(bind, endpint);
  16. Console.WriteLine(client.Add(1, 2));
  17. }
  18. }
  19. }

先后运行客户端与服务端,发现报了一个异常。

再来看看TcpTrace截取的请求消息:

<To>报头地址的端口变成了9999。即使TcpTrace进行了转发,因为逻辑地址不匹配,这样的消息无法通过服务端终结点的地址筛选器。

三、
如果想让上述客户端能够正常访问服务端。在自定义的类库的服务行为将AddressFilterMode设置成AddressFilterMode.Any,即使请求的<To>逻辑地址与服务端终结点逻辑地址不一致也可以访问。

  1. using System.ServiceModel;
  2. namespace mywcf
  3. {
  4. [ServiceBehavior(AddressFilterMode=AddressFilterMode.Any)]
  5. public class Calculator : ICalculator
  6. {
  7. public int Add(int x, int y)
  8. {
  9. return x + y;
  10. }
  11. }
  12. }

四、

客户端访问的监听地址也可以通过配置文件进行配置。配置如下,通过clientVia标签将监听地址端口设置为9999。逻辑地址的端口是8888。

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <configuration>
  3. <system.serviceModel>
  4. <behaviors>
  5. <endpointBehaviors>
  6. <behavior name="bindbehavior">
  7. <clientVia viaUri="http://localhost:9999"/>
  8. </behavior>
  9. </endpointBehaviors>
  10. </behaviors>
  11. <client>
  12. <endpoint address="http://localhost:8888" binding="wsHttpBinding" contract="mywcf.ICalculator" behaviorConfiguration="bindbehavior" name="myendpoint"></endpoint>
  13. </client>
  14. </system.serviceModel>
  15. </configuration>

WCF-终结点之消息路由示例的更多相关文章

  1. WCF初探-21:WCF终结点(endpoint)

    WCF终结点概述 在之前文章的示例中,我们都是通过配置服务的终结点(endpoint)发布的服务,供客户端调用,这是因为WCF服务的所有通信都是通过该服务的终结点进行的.每个终结点(endpoint) ...

  2. WCF终结点——终结点地址(EndpointAddress)

    终结点的地址的Uri属性作为终结点地址的唯一标示. 包括客户端终结点和服务端终结点. 一.服务端终结点: 服务端的终结点通过宿主的添加方法暴露出来,从而成为可以调用的资源. 下面是将服务绑定到宿主的代 ...

  3. 【.net 深呼吸】记录WCF的通信消息

    前面老周给大伙伴们介绍了把跟踪信息写入日志文件的方法,今天咱们换个类似的话题来扯一下,对了,咱们就说说怎么把WCF的往来消息log下来吧. 尽管在现实生活中,我们不主张偷窥他人信息,不过,偷窥程序信息 ...

  4. 【rabbitmq】rabbitmq概念解析--消息确认--示例程序

    概述 本示例程序全部来自rabbitmq官方示例程序,rabbitmq-demo: 官方共有6个demo,针对不同的语言(如 C#,Java,Spring-AMQP等),都有不同的示例程序: 本示例程 ...

  5. Azure IoT Hub 十分钟入门系列 (3)- 使用消息路由将原始设备数据记录存档

    本文主要分享一个案例: 10分钟使用消息路由将原始设备数据记录存档 B站视频讲解:https://www.bilibili.com/video/av90223893/ 本文主要有如下内容: 1.理解什 ...

  6. BizTalk动手实验(八)消息路由

    1 课程简介 通过本课程熟悉BizTalk消息由的机制 2 准备工作 1. 熟悉XML.XML Schema.XSLT等相关XML开发技术 2. 新建BizTalk空项目 3 演示 3.1 动态消息路 ...

  7. [老老实实学WCF] 第九篇 消息通信模式(上) 请求应答与单向

    老老实实学WCF 第九篇 消息通信模式(上) 请求应答与单向 通过前两篇的学习,我们了解了服务模型的一些特性如会话和实例化,今天我们来进一步学习服务模型的另一个重要特性:消息通信模式. WCF的服务端 ...

  8. 即时通信系统Openfire分析之四:消息路由

    两个人的孤独 两个人的孤独,大抵是,你每发出去一句话,都要经由无数网络.由几百个计算机处理后,出在他的面前,而他就在你不远处. 连接管理之后 Openfire使用MINA网络框架,并设置Connect ...

  9. 『片段』Win32 模式窗体 消息路由

    需求背景 近来,有个需求: 和一个外部程序对接. 具体是,我这边 主程序用 Process 启动外部程序.外部程序启动后,我这边调用的窗体不允许再进行任何操作. 当外部程序关闭时,外部程序会向我这边的 ...

随机推荐

  1. NET Core 拓展方法和中间件集合(支持NET Core2.0+)

    # Pure.NETCoreExtentensions https://github.com/purestackorg/Pure.NETCoreExtensions NET Core 拓展方法和中间件 ...

  2. SQL去除重复记录

    SQL去除重复记录 if not object_id('Tempdb..#T') is null     drop table #T Go Create table #T([ID] int,[Name ...

  3. docker为什么适合devops?

    欢迎访问网易云社区,了解更多网易技术产品运营经验 进阶版结论:Kubernetes + Docker 是 Dev 和 Ops 融合的一个桥梁.   DevOps 强调的是高效组织团队之间如何通过自动化 ...

  4. Docker 修改镜像源地址

    Docker 官方中国区 https://registry.docker-cn.com 网易 http://hub-mirror.c.163.com ustc https://docker.mirro ...

  5. GO学习笔记 - 包内首字母大写的名称是被导出的,才能被其它包代码调用!

    在GO语言的任意包内,如果名称的首字母是大写的,意味着这个名称被导出,在其它包中可以使用“包名.名称”方式来调用,如果名称首字母不是大写,那么只能在这个包内部使用!这个概念还真是和以往接触的编程语言的 ...

  6. 利用C# CefSharp Python采集某网站简历并自动发送邀请短信

    以往爬虫没怎么研究过,最近有个需求,要从某网站采集敏感信息,稍稍考虑了一下,决定利用C# Winform和Python一起来解决这个事件. 整个解决方案不复杂:C#编写WinForm窗体,进行数据分析 ...

  7. C++与C的区别二

    1. new,delete的局部重载: #include <iostream> using namespace std; ; class myclass { public: myclass ...

  8. 核心API的使用(给定一个字符串,统计每个字符出现的次数)

    /** * 给定一个字符串,统计每个字符出现的次数. 如:abdaewrwqask435a1aasd */public class ReplaceString { static int length; ...

  9. HDU-1260-Tickets(线性DP,DP入门)

    Tickets Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su ...

  10. ES6之新增const命令使用方法

    hi,我又回来了,今天学习一下const命令. 声明一个常量 const声明一个只读常量,一旦声明,常量的值便不可改变. 例子如下: const food = 12; food = 23; // Un ...