WCF专题系列(5):深入WCF寻址Part 5—逻辑地址和物理地址
[2] WCF专题系列(5):深入WCF寻址Part 5—逻辑地址和物理地址
[3] WCF专题系列(5):深入WCF寻址Part 5—逻辑地址和物理地址
设定物理地址
前面我们输出的结果逻辑地址和物理地址是相同的,我们可以通过代码或者配置文件来设定终结点的物理地址。
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="http://localhost:8887/CalculatorService" 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:calcservicewsa10: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="http://localhost:8887/CalculatorService" /> behavior> endpointBehaviors> behaviors> system.serviceModel>
此时客户端将通过与服务终结点相同的物理地址(http://localhost:8887/CalculatorService)向外传送消息而不是通过“urn:calcservice”,但请注意,在SOAP消息“To”标头中包含的仍然是逻辑地址,如图2所示:
图2
看到上面这幅图,可能大家还有一个疑问,逻辑地址起什么作用呢?别忘了我们前面讲到的消息筛选,当消息到达时,ChannelDispatcher 查询每个相关的 EndpointDispatcher 对象以确定终结点是否可以接受消息,以及将该消息传递到可以接受消息的终结点。当消息的目标地址(To标头中的地址)与 AddressFilter 属性相匹配并且消息操作与 ContractFilter 属性相匹配时,EndpointDispatcher 对象负责处理来自 ChannelDispatcher 的消息。