WCF终结点——终结点地址(EndpointAddress)
终结点的地址的Uri属性作为终结点地址的唯一标示。
包括客户端终结点和服务端终结点。
一、服务端终结点:
服务端的终结点通过宿主的添加方法暴露出来,从而成为可以调用的资源。
下面是将服务绑定到宿主的代码:
定义宿主时使用的是契约的实现类,也即服务类,添加终结点到宿主的使用的是契约接口。
1.1代码实现
代码实现往指定服务的宿主上添加终结点:
1.2配置实现
下面通过配置实现:
代码实现对应的配置如下:
1.3svc文件的配置
下面也给出svc文件中的配置:
由于svc文件被部署到了IIS上,所以对应的有端口,本身svc是一个文件,对应的也有路径,所以配置不用使用address字段
1.4获取宿主上的终结点
可以向一个宿主身上添加多个服务终结点,所以一个服务可以有多个终结点。每一个服务对应着一个宿主。当然可以获取所有的终结点。
宿主有个关于服务的描述属性,该属性包括了宿主的承载的所有服务终结点
1.5使用基地址+相对地址类添加契约终结点
当终结点比较多时,并且前面的部分相同时,可以通过基地址+相对地址类来添加终结点到宿主上面。
宿主这时也会根据使用的Binding类型的不同来区分请求的终结点。注意上面的一个是NetTcpBinding,一个是BasicHttpBinding。这就要求同一种绑定类型的基地址只能有一种,要不然会弄乱的。
下面是配置方式
IIS来讲文件所在地点就是基地址:
1.6当一个服务同时实现了两个契约时,需要共享相同的地址,那么必须保证其绑定是同一个。方法是new一个绑定供两个终结点使用。
二、客户端终结点
客户端通过引用服务,最终生成了一个代理类:客户端服务代理类继承自ClientBase<TChannel>和TChannel,其中TChannel是和服务端等效的接口,不过名称是自动生成的,我们可以使用此代理类来操作数据;也可以通过ChannelFactory<TChannel>来创建代理类来操作数据。
下面看简单的看一下代理类的基类的部分构造方法和两个属性。下面的属性有个ChannelFactory<TChannel>,其实第一种方法的代理是通过ClientBase<TChannel>的属性创建的。
public abstract class ClientBase<TChannel>
{
protected ClientBase();
protected ClientBase(ServiceEndpoint endpoint);
protected ClientBase(string endpointConfigurationName);
protected ClientBase(Binding binding, EndpointAddress remoteAddress);
protected ClientBase(string endpointConfigurationName, EndpointAddress remoteAddress);
protected ClientBase(string endpointConfigurationName, string remoteAddress);
protected TChannel Channel { get; }
public ChannelFactory<TChannel> ChannelFactory { get; }
}
为什么客户端能调用服务端的方法类操作数据?
由构造函数来看主要是通过使用终结点来和服务端相对应,来让客户端能够找到服务端的对象。
下面给出客户端的终结点的第一种配置:
<system.serviceModel>
<client>
<endpoint name="myEndPoint"
address="http://127.0.0.1/wcfservices/"
binding="wsHttpBinding"
contract="ServiceReference1.ICalculator">
</endpoint>
</client>
</system.serviceModel>
如果是使用上面的配置,那么就可以使用基类参数为endpointConfigurationName=myEndPoint的构造方法构造。
三、地址报头
每个终结点都含有一个Headers属性,客户端来说会被添加到请求消息的报头集合中,对于服务端来说,会提取响应的报头信息和本地终结点的地址报头来进行比较以选择出于请求消息相匹配的终结点。
地址报头的创建
AddressHeader CreateAddressHeader(string name, string ns, object value, XmlObjectSerializer serializer);
以下是服务端终结点的形状:
下面是如何使用地址报头的代码:
using (ChannelFactory<CalculatorService> channelFactory = new ChannelFactory<CalculatorService>("wsHttpBinding"))
{
CalculatorService calculator = channelFactory.CreateChannel();
Uri uri = new Uri("http://127.0.0.1:3721/calculatorservice");
AddressHeader header = AddressHeader.CreateAddressHeader("Licensed User", "http://www.artech.com", "UserType");
using (OperationContextScope operationContextScope=new OperationContextScope(calculator as IContextChannel))
{
OperationContext.Current.OutgoingMessageHeaders.Add(header.ToMessageHeader());
double result = calculator.Divide(1, 2);
}
}
如果AddressFilterMode为Any,报头可以不匹配。使用如下:
[ServiceBehavior(AddressFilterMode=AddressFilterMode.Any]
public class CalculatorService:ICalculator
四、逻辑地址和物理地址
物理地址对于服务端来说是监听地址,对于客户端来说是真正发送的目标地址。
针对SOAP的消息交换来说,服务的逻辑地址是<To>报头的地址。
对于服务端来说物理地址和逻辑地址分离的表现在:用于监听地址和收到的消息TO报头的地址不一致。
在客户端表现逻辑地址和物理地址分离的表现:<To>的报头地址和消息真正发送目标地址不一致。
需要中介服务参与消息路由的通信就涉及物理地址和逻辑地址的分离。
对于服务消费者来说,消息发送的逻辑地址是针对服务的最终提供者的。
<endpoint address="http://127.0.0.1:5555/service1"
binding="basicHttpBinding"
contract="Artech.WcfServices.Service.Interface.ICalculator" />
<!--2. BasicHttpBinding + ListenUriMode.Unique-->
<!--6666加GUID-->
<endpoint address="http://127.0.0.1:6666/service2"
binding="basicHttpBinding"
contract="Artech.WcfServices.Service.Interface.ICalculator"
listenUriMode="Unique" />
<!--3. NetTcpBinding & ListenUriMode.Explicit-->
<!--7777-->
<endpoint address="net.tcp://127.0.0.1:7777/service3"
binding="netTcpBinding"
contract="Artech.WcfServices.Service.Interface.ICalculator"/>
<!--4. NetTcpBinding & ListenUriMode.Unique-->
<!--会使用未占用的端口-->
<endpoint address="net.tcp://127.0.0.1:8888/service4"
binding="netTcpBinding"
contract="Artech.WcfServices.Service.Interface.ICalculator"
listenUriMode="Unique" />
<!--5. NetTcpBinding & ListenUriMode.Unique & Port Sharing-->
<!--会使用原来的端口,后面加个GUID-->
<endpoint address="net.tcp://127.0.0.1:9999/service5"
binding="netTcpBinding"
bindingConfiguration="PortSharingBinding"
contract="Artech.WcfServices.Service.Interface.ICalculator"
listenUriMode="Unique" />
上面的配置主要说明了监听地址和监听方式决定了最终的监听地址。
using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
{
host.Open();
int i = 0;
foreach (ChannelDispatcher channelDispatcher in host.ChannelDispatchers)
{
Console.WriteLine("{0}: {1}", ++i, channelDispatcher.Listener.Uri);
}
Console.ReadKey();
}
提供服务的主机,对应着一个或者多个分发器,每个分发器对应着一个或多个监听器。
wcf提供了4中类型的行为:1.服务行为、2契约行为、3终结点行为、4操作行为。行为是客户端或者服务端本地实现某个功能的一种方式,是一种单边的行为。
2和4被定义为特性。3只能通过配置,1可以声明和配置。1.服务行为,主要用于service behaviorConfiguration="" 。3.终结点行为主要用于终结点的endpoint endpointConfiguration=""
服务和终结点的行为配置如下:
终结点行为配置还可以如下:
<behaviors>
<endpointBehaviors>
<behavior name="aa" >
<clientVia viaUri="http://127.0.0.1:55551/service1"/>
</behavior>
</endpointBehaviors>
</behaviors>
上面的viaUri是代表的是物理地址,即消息真正发送的目的地址。
实现服务端逻辑地址和物理地址的分离的demo
客户端配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<ws2007HttpBinding>
<binding name="myBinding">
<security mode="None"/>
</binding>
</ws2007HttpBinding>
</bindings>
<client>
<endpoint name="calculatorservice"
address="http://127.0.0.1:9999/calculatorservice"
binding="ws2007HttpBinding"
bindingConfiguration="myBinding"
contract="Artech.WcfServices.Service.Interface.ICalculator"/>
</client>
</system.serviceModel>
</configuration>
服务端配置:
<system.serviceModel>
<bindings>
<ws2007HttpBinding>
<binding name="myBinding">
<security mode="None"/>
</binding>
</ws2007HttpBinding>
</bindings>
<services>
<service name="Artech.WcfServices.Service.CalculatorService">
<endpoint address="http://127.0.0.1:9999/calculatorservice"
binding="ws2007HttpBinding"
bindingConfiguration="myBinding"
contract="Artech.WcfServices.Service.Interface.ICalculator"
listenUri="http://127.0.0.1:8888/CalculatorService"
listenUriMode="Explicit"/>
</service>
</services>
</system.serviceModel>
路由转发设置:监听9999,目的8888.To包含的是9999.
接下来是客户端逻辑地址和物理地址的分离的实例:
服务端
<system.serviceModel>
<bindings>
<ws2007HttpBinding>
<binding name="myBinding">
<security mode="None"/>
</binding>
</ws2007HttpBinding>
</bindings>
<services>
<service name="Artech.WcfServices.Service.CalculatorService">
<endpoint address="http://127.0.0.1:9999/calculatorservice"
binding="ws2007HttpBinding"
bindingConfiguration="myBinding"
contract="Artech.WcfServices.Service.Interface.ICalculator"/>
</service>
</services>
</system.serviceModel>
客户端地址
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="clientVia">
<clientVia viaUri="http://127.0.0.1:8888/calculatorservice"/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<ws2007HttpBinding>
<binding name="myBinding">
<security mode="None"/>
</binding>
</ws2007HttpBinding>
</bindings>
<client>
<endpoint name="calculatorservice"
address="http://127.0.0.1:9999/calculatorservice"
binding="ws2007HttpBinding"
bindingConfiguration="myBinding"
behaviorConfiguration="clientVia"
contract="Artech.WcfServices.Service.Interface.ICalculator"/>
</client>
</system.serviceModel>
路由转发从8888转到9999,双方的Address必须相同,为了让<To>内的地址相同。可以知道发送到哪里。
信道分发器进行请求监听和消息接受,终结点分发器最终完成对消息的处理。
信道分发器相当于保安,当有人找公司里面的人时,保安会通知具体的公司人去处理事情。
WCF终结点——终结点地址(EndpointAddress)的更多相关文章
- 【WCF】终结点的监听地址
终结点主要作用是向客户端公开一些信息入口,通过这个入口,可以找到要调用的服务操作.通常,终结点会使用三个要素来表述,我记得老蒋(网名:Artech,在园子里可以找到他)在他有关WCF的书里,把这三要素 ...
- 【WCF】自定义地址头的筛选器
前面的文章中,老周已向大伙伴们介绍了如何在终结点上使用地址头,只要服务是沿着该终结点调用的,那么每一次调用都会自动把地址头插入到SOAP消息的Header列表中. 而通过前一篇文章中的示例,大家也看到 ...
- WCF: 没有终结点在侦听可以接受消息的 这通常是由于不正确的地址或者 SOAP 操作导致的。
问题: 由于我这里的wcf服务是采用“BasicHttpBinding”的方式,即安全绑定模式,客户端在引用这个服务后所生成的终结点配置(endpoint )就变成了<endpoint ...
- [Solution] 一步一步WCF(2) 终结点Endpoint
繁忙的一天又一天,不管其他,先继续WCF吧. Endpoint包含地址,绑定,契约三要素.WCF作为一个Windows平台下最大的通信框架.通过终结点承载了所有通信功能.所以终结点的作用将非常重要. ...
- WCF 配置终结点并调用服务
wcf通过xml文件配置终结点什么的感觉有点小麻烦,个人还是觉得用代码形式配置比较好,当然在发布的时候可能会比较麻烦,需要重新编译... 下面将wcf service寄宿在控制台应用程序中并配置终结点 ...
- wcf 远程终结点已终止该序列 可靠会话出错
https://social.msdn.microsoft.com/Forums/office/zh-CN/9f0c76d2-85b0-4cd3-979d-ceda7947bcd1/-?forum=w ...
- wcf客户端终结点样本集合
1. <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IUser" /&g ...
- WCF *.svc 自定义地址路由映射
一般在创建WCF服务时会用Serivce.svc文件访问,地址如:http://localhost/applicationname/Serivce.svc/Name 现在用路由映射成:http://l ...
- 【WCF】为终结点地址应用地址头
记得不久前,老周写过博文,探讨过在ContextScope以一定的范内向发出的消息中插入消息头,scope只能为特定的某一次服务操作的调用而添加SOAP头,要是需要在每次调用操作协定的时候都插上Hea ...
随机推荐
- 【Redis】Redis的常规操作命令
NoSQL是一种非关系型数据库,非关系型数据库库和传统的关系型数据库不同,非关系性体现在不需要依赖表进行数据存储.常见的非关系型数据库有Redis.MonoDB.HBase等,这些是基于key-val ...
- Swift 值类型/引用类型
1.值类型/引用类型 在 Swift 语言中,所有的类型都可以被分为 "值类型" 或者 "引用类型",可以将其理解为函数参数传递的方式. 值类型表示的是将它传递 ...
- NET MVC全局异常处理(一) 【转载】网站遭遇DDoS攻击怎么办 使用 HttpRequester 更方便的发起 HTTP 请求 C#文件流。 Url的Base64编码以及解码 C#计算字符串长度,汉字算两个字符 2019周笔记(2.18-2.23) Mysql语句中当前时间不能直接使用C#中的Date.Now传输 Mysql中Count函数的正确使用
NET MVC全局异常处理(一) 目录 .NET MVC全局异常处理 IIS配置 静态错误页配置 .NET错误页配置 程序设置 全局异常配置 .NET MVC全局异常处理 一直知道有.NET有相关 ...
- linux 文件系统 xfs、ext4、ext3 的区别
前言 centos7.0开始默认文件系统是xfs,centos6是ext4,centos5是ext3 ext3介绍 ext3和ext4的最大区别在于,ext3在fsck时需要耗费大量时间(文件越多,时 ...
- 【转载】Hibernate之hbm.xml集合映射的使用(Set集合映射,list集合映射,Map集合映射)
https://www.cnblogs.com/biehongli/p/6555994.html
- Hive实现从表中随机抽样得到一个不重复的数据样本
select a.* from ( select a.*,rand(12345) as random from tripdata a ) a where random between 0 and 0. ...
- springcloud中服务组策与发现eureka
1 Eureka 是什么 Eureka是netflix的一个子模块,只需要使用服务的标志符,就可以访问到服务,而不需要修改服务调用的配置文件.功能类似于Dubbo的注册中心,比如Zookeeper. ...
- ARM:移动GPU往PC GPU效能迈进
行动装置的热潮持续不退,各大手机制造商除了想尽办法推出外型酷炫的行动装置设备来吸引消费者的目光之外,更在行动应用处理器玩起多核心的「核」战争,无非是希望能够带给消费者更优异的效能新体验.然而,随着消费 ...
- python3 元类编程的一个例子
[引子] 虽然我们可以通过“class”语句来定义“类”,但是要想更加细粒度的控制“类”的创建,要使用元类编程才能实现. 比如说我们要实现这样的一个约束.所有项目中用到的类都应该要为它定义的方法提供文 ...
- js函数调用二种常用方法的例子
js中函数调用的两种常用方法. 一个js函数 function test(aa){ window.alert("你输入的是"+aa); } 方法一:直接调用 test(" ...