【问题标题】:WCF service discovery with dynamic port 0 and TCP binding具有动态端口 0 和 TCP 绑定的 WCF 服务发现
【发布时间】:2015-02-13 20:25:14
【问题描述】:

我想在端口 0 上启动一项服务(使用 mex TCP 绑定启用 Mex) - 比如说在使用网络 TCP 绑定的端点上的合同“IHelloWorldOne”。

来自我的服务的 App.config

  <service name="Service.One.HelloWorldOne">
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" name="Mex" kind="mexEndpoint" listenUriMode="Unique" />
    <endpoint name="Discovery" kind="udpDiscoveryEndpoint" />
    <endpoint address="1/tcp" binding="netTcpBinding" name="Service.One" contract="Service.One.IHelloWorldOne" listenUriMode="Unique" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:0/service" />
      </baseAddresses>
    </host>
  </service>

请注意,端口为 0 - 这基本上让 windows 为我提供一个开放端口作为端点,这意味着“mex”端点可以获得一个随机端口。

在我的客户端上:

        FindCriteria findCriteria = FindCriteria.CreateMetadataExchangeEndpointCriteria(typeof(IHelloWorldOne));
        //FindCriteria findCriteria = new FindCriteria(typeof(IHelloWorldOne));
        findCriteria.MaxResults = 1;
        findCriteria.Duration = TimeSpan.FromSeconds(5);
        findCriteria.Scopes.Add(new Uri(string.Format("net.tcp://sharedservice/{0}/", "SHAREDCONTEXT")));

        FindResponse response = discoveryClient.Find(findCriteria);
        try
        {
            if (response.Endpoints.Count > 0)
            {
                var mexClient = new MetadataExchangeClient(MetadataExchangeBindings.CreateMexTcpBinding());
                var contracts = new List<ContractDescription>() { ContractDescription.GetContract(typeof(IHelloWorldOne)) };
                EndpointAddress address = new EndpointAddress(response.Endpoints[0].ListenUris[0]);
                var endpoints = MetadataResolver.Resolve(contracts, address, mexClient);

注意:我使用 ListenURI 来交换元数据。但是,当我尝试这样做时 - 我遇到了这个异常

例外

System.InvalidOperationException: Metadata contains a reference that cannot be resolved: 'net.tcp://localhost:50294/service/mex'. --->
System.InvalidOperationException: <?xml version="1.0" encoding="utf-16"?><Fault xmlns="http://www.w3.org/2003/05/soap-envelope"><Code><Value>Sender</Value><Subcode><Value xmlns:a="http://www.w3.org/2005/08/addressing">a:DestinationUnreachable</Value></Subcode></Code><Reason><Text xml:lang="en-US">
The message with To 'net.tcp://localhost:50294/service/mex' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher.  
Check that the sender and receiver's EndpointAddresses agree.</Text></Reason></Fault>

我可以在 listenURI 上看到 mex 端点的端口,但无法连接到它。

我尝试的另一种方法是将 mex 端点保留为常量并发现服务端口 - 我无法完成此操作,并且响应中端点的 listenURI 上的端口不可用。

所以我的问题是,有没有办法为 Mex 和服务端点绑定到 WCF 中的端口 0 并发现它们?如果有,怎么做?

【问题讨论】:

    标签: .net wcf tcp wcf-binding ws-discovery


    【解决方案1】:

    来自您的异常消息:

    EndpointDispatcher 的地址过滤器不匹配

    这是因为端点地址应该与创建端点时指定的完全相同(例如端口 = 0)

    问题是 MetadataResolver 没有使用以下重载 MetadataExchangeClient 类

    public MetadataSet GetMetadata(
        EndpointAddress address,
        Uri via
    )
    

    这里 address 应该是你的情况 response.Address (使用端口 0)

    via 参数应该是它在您的情况下侦听的端点的实际 Uri(例如,具有实际端口号)response.Endpoints[0].ListenUris[0].

    似乎没有简单的方法可以将 MetadataResolver 与动态端口一起使用。

    在我的情况下,我在动态端口上有服务,并使用发现来查找分配给服务的端口。

    在客户端我使用以下代码:

    FindResponse response = discoveryClient.Find(findCriteria);
    var binding = new NetTcpBinding(SecurityMode.None);
    return ChannelFactory<IMyService>.CreateChannel(binding, response.Endpoints[0].Address, response.Endpoints[0].ListenUris[0]);
    

    这里我用端口 0 指定端点地址,用 ListenUris 动态分配的端口指定实际地址。

    希望这将有助于解决您的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-14
      • 1970-01-01
      • 1970-01-01
      • 2010-09-22
      • 1970-01-01
      • 2017-09-19
      • 2012-08-17
      • 1970-01-01
      相关资源
      最近更新 更多