在WCF中,每个终结点都包含两个不同的地址:逻辑地址和物理地址。逻辑地址就是以终结点Address属性表示的地址。至于物理地址,对于消息发送端来讲,就是消息被真正发送的目的地址;而对于消息接收端来讲,就是监听器真正监听的地址,也称为监听地址。
逻辑地址
终结点的逻辑地址由EndpointAddress类来表示,用于查找和标识终结点。该类包含Uri属性、一组可选的Headers属性(定义到达服务所需的任何其他SOAP头)和一个可选的Identity属性。
物理地址
对于物理地址,在服务端由ServiceEndpoint类中的ListenUri属性和ListenUriMode属性表示;在客户端通过一个特殊的EndpointBehavior来指定:ClientViaBehavior。ClientViaBehavior定义的URI代表该物理地址。
例如,对于如下配置:
<system.serviceModel>
<services>
<service name="Wcf.CalculatorService">
<endpoint address="http://localhost:7777/WcfService1" binding="wsHttpBinding" contract="Wcf.ICalculatorService"
listenUri="http://localhost:6666/WcfService" listenUriMode="Explicit"/>
<endpoint address="http://localhost:8888/WcfService2" binding="wsHttpBinding" contract="Wcf.ICalculatorService"
listenUri="http://localhost:6666/WcfService" listenUriMode="Explicit"/>
<endpoint address="http://localhost:9999/WcfService3" binding="wsHttpBinding" contract="Wcf.ICalculatorService"
listenUri="http://localhost:6666/WcfService" listenUriMode="Unique"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
遍历ServiceHost的Dispatcher:
foreach (var dispatcherBase in host.ChannelDispatchers)
{
var channelDispatcher = dispatcherBase as ChannelDispatcher;
Console.WriteLine("ChannelDispatcher - {0}", channelDispatcher.Listener.Uri);
foreach (var endpointDispatcher in channelDispatcher.Endpoints)
{
Console.WriteLine("\tEndpointDispatcher - {0}", endpointDispatcher.EndpointAddress.Uri);
}
}
将会得到如下结果:
结果表明有两个物理地址和三个逻辑地址。
这时,客户端需要通过如下配置调用服务:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="clientViaBehavior">
<clientVia viaUri="http://localhost:6666/WcfService"/>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint name="CalculatorService" address="http://localhost:8888/WcfService2" binding="wsHttpBinding" contract="Wcf.ICalculatorService"
behaviorConfiguration="clientViaBehavior"/>
</client>
</system.serviceModel>