在单个 ListenUri 中承载多个终结点

MultipleEndpointsSingleUri 示例演示了一个服务,该服务在单个ListenUri终结点上托管多个终结点。 此示例基于《入门指南》,实现了计算器服务。

注释

本示例的设置过程和生成说明位于本主题末尾。

“多个终结点” 示例中所示,服务可以托管多个终结点,每个终结点具有不同的地址,也可能是不同的绑定。 此示例演示如何在同一地址托管多个终结点。 此示例还演示了服务终结点具有的两种地址之间的差异: EndpointAddressListenUri

EndpointAddress 是服务的逻辑地址。 这是 SOAP 消息的目的地址。 服务 ListenUri 的物理地址。 它具有服务终结点在当前计算机上侦听消息时所用的端口和地址信息。 在大多数情况下,这些地址不需要有所不同;如果未显式指定 ListenUri,则默认为终结点的 EndpointAddress URI。 在少数情况下,区分它们非常有用,例如配置路由器时,路由器可能会接受发送到多个不同服务的消息。

服务

此示例中的服务有两个协定, ICalculator 以及 IEcho。 除了自定义 IMetadataExchange 终结点,还有三个应用程序终结点,如以下代码所示。

<endpoint address="urn:Stuff"
        binding="wsHttpBinding"
        contract="Microsoft.ServiceModel.Samples.ICalculator"
        listenUri="http://localhost/servicemodelsamples/service.svc" />
<endpoint address="urn:Stuff"
        binding="wsHttpBinding"
        contract="Microsoft.ServiceModel.Samples.IEcho"
        listenUri="http://localhost/servicemodelsamples/service.svc" />
<endpoint address="urn:OtherEcho"
        binding="wsHttpBinding"
        contract="Microsoft.ServiceModel.Samples.IEcho"
        listenUri="http://localhost/servicemodelsamples/service.svc" />

所有这三个终结点都在同一个 ListenUri 中承载,而且使用相同的 binding(即,位于同一个 ListenUri 的终结点必须具有相同的绑定),这是由于它们共享一个通道堆栈,而且该通道堆栈在计算机中的该物理地址上侦听消息。 address每个终结点都是一个 URN;虽然通常地址表示物理位置,但实际上地址可以是任何类型的 URI,因为该地址用于匹配和筛选目的,如此示例所示。

由于这三个终结点共享相同 ListenUri,因此当消息到达那里时,Windows Communication Foundation (WCF) 必须决定消息所面向的终结点。 每个终结点都有一个消息筛选器,其中包含两个部分:地址筛选器和协定筛选器。 地址筛选器将 SOAP 消息与 To 服务终结点的地址匹配。 例如,只有发送到 To "Urn:OtherEcho" 的消息才是该服务的第三个候选终结点。 协定筛选器与那些与特定协定的操作相关联的 Action 相匹配。 例如,具有 IEcho 操作的消息。 Echo 匹配此服务的第二个和第三个终结点的协定筛选器,因为这两个终结点都托管 IEcho 协定。

因此,地址筛选器和协定筛选器的组合使得可以将到达此服务 ListenUri 的每个消息路由到正确的终结点。 第三个终结点与其他两个终结点区分开来,因为它接受发送到其他终结点不同地址的消息。 前两个终结点的区别在于它们的协定(传入消息的 Action)不同。

客户

就像服务器上的终结点有两个不同的地址一样,客户端终结点也有两个地址。 在服务器和客户端上,逻辑地址称为EndpointAddress。 但是,在服务器上,物理地址被称为ListenUri ,而在客户端上,物理地址被称为Via

与在服务器上一样,默认情况下,这两个地址是相同的。 若要在客户端上指定与终结点地址不同的 Via,请使用 ClientViaBehavior:

Uri via = new Uri("http://localhost/ServiceModelSamples/service.svc");
CalculatorClient calcClient = new CalculatorClient();
calcClient.ChannelFactory.Endpoint.Behaviors.Add(
        new ClientViaBehavior(via));

与往常一样,地址来自客户端配置文件,而该文件是由 Svcutil.exe生成的。 Via(与服务的 ListenUri 相对应)不出现在服务的元数据中,因此该信息必须在带外传递到客户端(就像服务的元数据地址一样)。

此示例中的客户端将消息发送到服务器的每个三个应用程序终结点,以证明它可以与所有三个终结点通信(并区分),即使它们都具有相同 Via

设置、生成和运行示例

  1. 确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。

  2. 若要生成解决方案的 C# 或 Visual Basic .NET 版本,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。

  3. 若要在单台计算机或跨计算机配置中运行示例,请按照 运行 Windows Communication Foundation 示例中的说明进行操作。

    注释

    对于跨计算机,必须将 Client.cs 文件中的 localhost 替换为服务计算机的名称。