概述

在WCF中,每个服务终结点都与两个地址相关联,一个逻辑地址和一个物理地址,逻辑地址就是SOAP消息的目标地址,即前面不止一次提到的“To”地址,而物理地址是WCF侦听器真正监听的地址。在WCF中,逻辑地址称之为终结点地址Endpoint Address,而物理地址则称之为监听地址ListenUri。

本文将详细介绍WCF中的物理地址和逻辑地址,以及如何使用tcpTrace来进行SOAP消息的跟踪。

两种地址

WCF中,物理地址负责使用特定的传输协议在特定的位置接收传入的消息,除非特别指定,否则逻辑地址将被用来做物理地址,换句话说,在以前我们对于终结点所配置的EndpointAddress都是指定了逻辑地址,如我们的服务端配置如下:

<endpoint address="[url]http://localhost:8887/CalculatorService1[/url]"binding ="wsHttpBinding"contract="TerryLee.WCFAddressing.Contract.ICalculator">
</endpoint>
<endpoint address="[url]http://localhost:8887/CalculatorService2[/url]"binding ="basicHttpBinding"contract="TerryLee.WCFAddressing.Contract.ICalculator">
</endpoint>
现在我们输出一下,就可以看到两个地址是同样的值,如下代码所示:

using (ServiceHost calculatorServiceHost =new ServiceHost(typeof(CalculatorService)))
{calculatorServiceHost.Opened += delegate{Console.WriteLine("Service begin to listen via the Address:{0}",calculatorServiceHost.BaseAddresses[0].ToString());};calculatorServiceHost.Open();foreach (ServiceEndpoint se in calculatorServiceHost.Description.Endpoints){Console.WriteLine("Endpoint details:");Console.WriteLine("Logical address: \t{0}", se.Address);Console.WriteLine("Physical address: \t{0}", se.ListenUri);Console.WriteLine("Binding: \t{0}", se.Binding.Name);Console.WriteLine();}Console.Read();
}
输出结果如图1所示:

图1

设定物理地址

前面我们输出的结果逻辑地址和物理地址是相同的,我们可以通过代码或者配置文件来设定终结点的物理地址。

WSHttpBinding wsbinding = new WSHttpBinding();
calculatorServiceHost.AddServiceEndpoint(typeof(ICalculator),wsbinding,"urn:calcservice",  // 逻辑地址new Uri("http://localhost:8887/CalculatorService")  // 物理地址
);
又或者通过配置文件来设置ListenUri,如下代码所示:

<endpoint address="urn:calcservice"binding ="wsHttpBinding"contract="TerryLee.WCFAddressing.Contract.ICalculator"listenUri="[url]http://localhost:8887/CalculatorService[/url]"bindingConfiguration="securityBinding">
</endpoint>
这里我们只需要注意的是在指定物理地址时,仍然可以使用相对地址,这一点与设置逻辑地址时是一样的。

工作原理

现在思考一个核心的问题,当我们定义了终结点后,在WSDL中包含的是每个终结点的逻辑地址,而非物理地址,如下代码片段:

<wsdl:service name="CalculatorService"><wsdl:port name="WSHttpBinding_ICalculator" binding="tns:WSHttpBinding_ICalculator"><soap12:address location="urn:calcservice" /><wsa10:EndpointReference><wsa10:Address>urn:calcservice</wsa10:Address></wsa10:EndpointReference></wsdl:port>
</wsdl:service>
如果物理地址与逻辑地址相同的,就不会有任何问题,但是客户端如何与一个配置了不同物理地址的服务进行交互?因为客户端并不关心服务端是否配置了不同的物理地址,它只知道每个终结点有一个唯一的终结点地址,只需要跟该地址交互即可,该地址也将作为SOAP消息放在“To”标头中。

这时我们需要有一个特殊机制,来通知客户端要使用的物理地址,然后客户端通过物理地址传送外发消息,就如同它是路由器或者某种类型的中介一样,可以通过ClientViaBehavior来实现这一点,如下代码所示:

<system.serviceModel><client><endpoint address="urn:calcservice"binding="wsHttpBinding"contract="TerryLee.WCFAddressing.Contract.ICalculator"name="defualtEndpoint"behaviorConfiguration="calculatorEndpointBehavior"bindingConfiguration="securityBinding"></endpoint></client><behaviors><endpointBehaviors><behavior name="calculatorEndpointBehavior"><clientVia viaUri="[url]http://localhost:8887/CalculatorService[/url]" /></behavior></endpointBehaviors></behaviors>
</system.serviceModel>
此时客户端将通过与服务终结点相同的物理地址([url]http://localhost:8887/CalculatorService[/url])向外传送消息而不是通过“urn:calcservice”,但请注意,在SOAP消息“To”标头中包含的仍然是逻辑地址,如图2所示:

图2

看到上面这幅图,可能大家还有一个疑问,逻辑地址起什么作用呢?别忘了我们前面讲到的消息筛选,当消息到达时,ChannelDispatcher 查询每个相关的 EndpointDispatcher 对象以确定终结点是否可以接受消息,以及将该消息传递到可以接受消息的终结点。当消息的目标地址(To标头中的地址)与 AddressFilter 属性相匹配并且消息操作与 ContractFilter 属性相匹配时,EndpointDispatcher 对象负责处理来自 ChannelDispatcher 的消息。

物理地址模式

了解了物理地址和逻辑地址之间的关系,我们再看一下在设置监听地址时的两种模式,通过ListenUriMode枚举来指定,它定义了两个枚举值:

Explicit:完全原样使用 ListenUri,默认值。

Unique:指定传输是否应使用特定传输机制,以确保 ListenUri 是唯一的

根据传输所采用的协议不同,WCF会采用不同的策略来保证ListenUri唯一,具体的策略如下所示:

1.非TCP传输,在ListenUri的末尾附加一个GUID。

2.对于独占模式下的 TCP(PortSharingEnabled 为 false),绑定到一个唯一可用端口号。

3.对于端口共享模式下的 TCP(PortSharingEnabled 为 true),在ListenUri的末尾附加一个GUID。

TcpTrace消息截获

前面讲了这么多物理地址和逻辑地址,它们最重要的使用地方就是做路由。我们常用tcpTrace来做SOAP消息跟踪,它正是利用这一点技术,在客户端配置ClientViaBehavior,指向tcpTrace的侦听地址,然后tcpTrace在对消息做记录后再转发到服务端,如在服务端的配置如下,它的物理地址和逻辑是相同的:

<service name="TerryLee.WCFAddressing.Service.CalculatorService"behaviorConfiguration="calculatorBehavior"><host><baseAddresses><add baseAddress="[url]http://localhost:8887/Calculator[/url]"/></baseAddresses></host><endpoint address="[url]http://localhost:8887/CalculatorService[/url]"binding ="wsHttpBinding"contract="TerryLee.WCFAddressing.Contract.ICalculator"></endpoint>
</service>
客户端的配置,这里“[url]http://localhost:8887/CalculatorService[/url]”是真正的服务地址(逻辑地址),我们通过ClientViaBehavior告诉客户端物理地址是“[url]http://localhost:8080/CalculatorService[/url]”,事实上处于该物理地址的服务并不存在,该地址是tcpTrace的监听地址:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><system.serviceModel><client><endpoint address="[url]http://localhost:8887/CalculatorService[/url]"binding="wsHttpBinding"contract="TerryLee.WCFAddressing.Contract.ICalculator"behaviorConfiguration="calculatorEndpointBehavior"></endpoint></client><behaviors><endpointBehaviors><behavior name="calculatorEndpointBehavior"><clientVia viaUri="[url]http://localhost:8080/CalculatorService[/url]" /></behavior></endpointBehaviors></behaviors></system.serviceModel>
</configuration>
tcpTrace的配置如图3所示:

图3

这里tcpTrace监听的端口号就是我们在客户端配置的物理地址端口号,而分发地址才是服务的真正地址,最终可以看到截获的消息,如图4所示:

图4

如果不在客户端配置ClientViaBehavior,利用物理地址和逻辑地址的知识,我们还可以有另外一种方式使用tcpTrace。前面我说过,逻辑地址是包含在WSDL中,所以对于客户端来说知道的是逻辑地址,它会向该地址发送消息,这样我们可以配置终结点的逻辑地址为tcpTrace侦听的地址,而为服务端指定另外一个物理地址,并配置tcpTrace向该物理地址转发消息,如服务端的配置如下:

<service name="TerryLee.WCFAddressing.Service.CalculatorService"behaviorConfiguration="calculatorBehavior"><host><baseAddresses><add baseAddress="[url]http://localhost:8080/Calculator[/url]"/></baseAddresses></host><endpoint address="[url]http://localhost:8887/CalculatorService[/url]"binding ="wsHttpBinding"contract="TerryLee.WCFAddressing.Contract.ICalculator"listenUri="[url]http://localhost:8080/CalculatorService[/url]"></endpoint>
</service>
而客户端则不用再配置ClientViaBehavior,如下代码所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><system.serviceModel><client><endpoint address="[url]http://localhost:8887/CalculatorService[/url]"binding="wsHttpBinding"contract="TerryLee.WCFAddressing.Contract.ICalculator"></endpoint></client></system.serviceModel>
</configuration>
现在“[url]http://localhost:8887/CalculatorService[/url]”是逻辑地址,配置tcpTrace监听该地址,并向服务的物理地址“[url]http://localhost:8080/CalculatorService[/url]”转发消息,如图5所示:

图5

可以看到,利用物理地址和逻辑地址的知识,可以轻松的实现路由,当然tcpTrace只是路由中非常简单的一种使用,后面我们还会讲到更加复杂的应用。

结束语

本文详细介绍了WCF中的物理地址和逻辑地址,它的相关原理以及如何使用tcpTrace来实现SOAP消息的跟踪。关于WCF寻址相关文章:

WCF专题系列(4):深入WCF寻址Part 4—自定义消息筛选器

WCF专题系列(3):深入WCF寻址Part 3—消息过滤引擎

WCF专题系列(2):深入WCF寻址Part 2—自定义寻址报头

WCF专题系列(1):深入WCF寻址Part 1—Web服务寻址规范

©著作权归作者所有:来自51CTO博客作者lihuijun的原创作品,如需转载,请注明出处,否则将追究法律责任
Address Endpoint WCF寻址 WCF后传

0

分享

微博 QQ 微信

收藏

上一篇:WCF后传系列(4):深入WCF... 下一篇:.NET Framework 4...
lihuijun

203篇文章,69W+人气,0粉丝

Ctrl+Enter 发布

发布

取消

推荐专栏更多

全局视角看大型园区网

路由交换+安全+无线+优化+运维

共40章 | 51CTO夏杰

¥51.00 1666人订阅

订   阅

网工2.0晋级攻略 ——零基础入门Python/Ansible

网络工程师2.0进阶指南

共30章 | 姜汁啤酒

¥51.00 1566人订阅

订   阅

基于Python的DevOps实战

自动化运维开发新概念

共20章 | 抚琴煮酒

¥51.00 430人订阅

订   阅

负载均衡高手炼成记

高并发架构之路

共15章 | sery

¥51.00 507人订阅

订   阅

带你玩转高可用

前百度高级工程师的架构高可用实战

共15章 | 曹林华

¥51.00 462人订阅

订   阅

猜你喜欢

我的友情链接 《Silverlight 2完美征程》:书稿目录 Windows 10 "升"与"不升"之我见 Windows server 2016 搭建RDS服务 kubernetes 存储卷与数据持久化 Windows 设置 VMware workstation 虚拟机开机启动 漫谈 Windows Server 管理工具 如何在Windows中批量创建VMware的虚拟机 解决asp.net负载均衡时Session共享的问题 中小企业2018-2020年信息化环境运维及安全建议 Windows10搭建标准的WAMP开发环境-httpd2.4+php7.2+mariadb10.3 HP Elitedesk&ProDesk更新win10十月更新蓝屏 WDF VIOLATION 从2008到2019 Windows Server 2019 存储迁移服务 PowerShell 如何让普通用户以管理员权限执行程序 反思一次Exchange服务器运维故障 一套老旧ASP+Access的复活记 通过Powershell调研EWS API删除特定主题邮件操作手册 升级SCCM 2012R2 SP1故障解决 AD域下DNS外迁

扫一扫,领取大礼包

0

分享

lihuijun

转载于:https://blog.51cto.com/terrylee/151946

WCF后传系列(5):深入WCF寻址Part 5—逻辑地址和物理地址相关推荐

  1. TerryLee技术专栏WCF后传正文 WCF后传系列(3):深入WCF寻址Part 3—消息过滤引擎...

    概述 通过前面两篇的介绍,对Web服务寻址规范以及在WCF开发中终结点地址有了深入的认识.本文我们继续深入WCF寻址第三部分内容,当消息传入时,如何来确定匹配的终结点,就是我们本文要讲到的消息筛选引擎 ...

  2. WCF后传系列(3):深入WCF寻址Part 3—消息过滤引擎

    概述 通过前面两篇的介绍,对Web服务寻址规范以及在WCF开发中终结点地址有了深入的认识.本文我们继续深入WCF寻址第三部分内容,当消息传入时,如何来确定匹配的终结点,就是我们本文要讲到的消息筛选引擎 ...

  3. WCF后传系列(2):深入WCF寻址Part 2—自定义寻址报头

    概述 在WCF专题系列(1):深入WCF寻址Part1一文中,我们对Web服务寻址规范做了一些认识,了解了终结点引用和消息信息报头两种结构,该规范在Web服务中的地位举足轻重,后续我们会经常提到该规范 ...

  4. [导入]WCF后传系列(8):深度通道编程模型Part 1—设计篇

    摘要: 从本质上说,WCF是一个通信服务框架,它允许我们使用不同的传输协议,使用不同的消息编码形式,跟不同的WS-*系列规范交互,而所有这些细节都是由通道堆栈来处理的.为了简化这些处理,在WCF中提供 ...

  5. [导入]WCF后传系列(6):消息如何传递之绑定Part 1

    摘要: 每个服务终结点都包含一个地址Address.一个绑定Binding 和一个契约Contract.契约指定可用的操作,绑定指定如何与服务进行通信,而地址指定查找服务的位置,在WCF专题系列前5篇 ...

  6. android wcf 上传文件,第二篇 ( wcf 与 android 图片上传下载)

    老规矩废话不多说,直接入主题 注:wcf 使用rest风格,传递json数据,图片是经过base64编码,android 使用common-codec-1.5.jar 进行base64编码 服务器端 ...

  7. Linux中的文件寻址,Linux文件寻址算法:逻辑地址到物理地址的转换

    题目描述: 编写一个函数实现Linux文件寻址的算法,即读取文件当前位置到物理存储位置的转换函数,需要给出运行的测试数据,可以假设和模拟需要的数据和结构.即编写一个函数unsigned long lt ...

  8. IOS And WCF 上传文件

    IOS And WCF Story 研究IOS上传到WCF图片的小功能,WCF实现服务端的文件上传的例子很多,单独实现IOS发送图片的例子也很多,但是两个结合起来的就很少了. 可以通过base64来上 ...

  9. WCF开发实战系列四:使用Windows服务发布WCF服务

    WCF开发实战系列四:使用Windows服务发布WCF服务 (原创:灰灰虫的家http://hi.baidu.com/grayworm) 上一篇文章中我们通过编写的控制台程序或WinForm程序来为本 ...

最新文章

  1. Vue学习小札——2.6 组件参数校验与非props特性
  2. Spring MVC报异常:org.springframework.web.util.NestedServletException: Request processing failed
  3. 设计模式-扩展-父类对子类的要求
  4. The type List is not generic
  5. 下一个嵌入式大神,难道不是你吗?
  6. 计算机应用与基础进制,计算机应用基础选择题-删进制、字符题(2).docx
  7. index.wxss 导入不显示结果
  8. Lua游戏开发----游戏搭建
  9. 【编译原理笔记05】语法分析:FIRST集和FOLLOW集的计算,[非]递归的预测分析法,预测分析中的错误处理
  10. 产品学习---互联网形势
  11. 快速入门Flink (7) —— 小白都喜欢看的Flink流处理之DataSources和DataSinks(转载)
  12. git提交错分支怎么办
  13. NC65 用户密码重置
  14. Jdt-compiler是什么?有什么作用
  15. mysql数据库的封装
  16. MySQL最全整理(面试题+笔记+导图),面试大厂不再被MySql难倒
  17. 【经验篇】聊聊双非计算机硕士如何进大厂搞算法
  18. JSPX使用的几点注意
  19. ubuntu20.04美化
  20. web怎么将dwg转换图片_CAD转JPG图片,在线转换成高质量彩色图片

热门文章

  1. Android EditText+ListPopupWindow实现可编辑的下拉列表
  2. 利用泛型接口实现生成器
  3. Eclipse开发struts完全指南
  4. 蓝桥杯:入门训练 圆的面积
  5. Linux系统使用apt命令安装java
  6. 单片机c语言编程300例_趣味c语言编程100例(四)
  7. vasp安装包_【问题集锦】VASPamp;MedeA 第十一期
  8. php程序设计依赖注入_PHP控制反转和依赖注入
  9. mysql迅速搭建网页_Django + mysql 快速搭建简单web投票系统
  10. jsp 修改的员工select怎么_jdbc+jsp实现简单员工管理系统|chu