【问题标题】:Ensuring that outgoing WCF requests are performed using a specific network interface确保使用特定网络接口执行传出 WCF 请求
【发布时间】:2013-07-09 15:38:02
【问题描述】:

我有一个从我的应用程序连接到的远程 WCF Web 服务。

应用程序可能在具有多个 IP 地址(或多个物理网络接口)的服务器上运行

我需要确保我可以控制用于出站请求的 IP 地址,而不是按照常规指标规则仅使用“首选”接口。

这样做的原因是软件的多个副本将在同一台机器上运行,每个副本都绑定到特定的 IP 地址以进行自己的操作,并且所连接的远程服务需要知道正在使用哪个稍后再连接(因为地址错误意味着连接到错误的服务)

对于旧版 ASMX 服务,这是通过覆盖为服务生成的部分类上的 GetWebRequest(Uri uri) 来完成的。但我完全不知道如何使用 WCF 来做到这一点。

unrelated SO post 上,MVP @JohnSaunders 建议这可以通过接管 WCF 使用的整个传输机制来实现。但我也还没想好怎么做。

【问题讨论】:

  • @BradChristie 第一个答案是操作系统级别,第二个答案不适用于 WCF,仅适用于原始 SOAP 请求,因此为什么该问题没有可接受的答案。
  • 顺便说一句,根据 IP 地址来决定要连接到哪个实例是……一个次优的解决方案。
  • 你检查了吗this link
  • “被连接的远程服务需要知道稍后使用哪个 [IP 地址] 连接回它” - 对我来说,但请更正如果我错了,这看起来像你试图解决一个太低级别的架构问题,如果可能的话。这不是要求双工通道,还是不能让客户端轮询远程 Web 服务而不是让客户端回调?

标签: c# wcf wcf-binding


【解决方案1】:

这是一个棘手的问题,WCF 似乎并不能很好地解决这个问题。

.NET 框架中唯一似乎直接处理客户端 地址问题的组件是ServicePoint 类。具体来说,它有一个BindIPEndPointDelegate 属性,可让您控制它如何选择客户端IP。该属性的文档包括:

某些负载平衡技术要求客户端使用特定的本地 IP 地址和端口号,而不是 IPAddress.Any(或 Internet 协议版本 6 的 IPAddress.IPv6Any)和临时端口。你的BindIPEndPointDelegate 可以满足这个要求。

因此,您应该能够在如下代码中修改与您的 URL 关联的服务点:

var servicePoint =  ServicePointManager.FindServicePoint(
    new Uri("http://contoso.com/service.svc"));

servicePoint.BindIPEndPointDelegate =
    (sp, remote, retryCount) => new IPEndPoint(address, portNumber);

显然,此类代码要求您的类了解协议和客户端将与之通信的端点地址。将此逻辑设置为可应用于您的客户端通道的客户端行为可能是最合适的。

【讨论】:

  • 我假设您使用的是 HTTP,因为您提到了 ASMX 服务。此解决方案仅适用于 HTTP 协议,因为 ServicePointManager 仅处理该堆栈。
【解决方案2】:

您可以使用消息属性 (HttpRequestMessageProperty) 将 HTTP 标头添加到任何传出请求。您需要创建一个“范围”,其中属性将添加到当前的“操作上下文”中,并将该属性与您想要的所有标题一起附加到上下文的传出消息属性中。

请看这个:

how-to-override-getwebrequest-method-using-service-reference-instead-of-web-reference-in-wcf

【讨论】:

    【解决方案3】:

    使用这个: 新课程:

    using System.Web.Services.Protocols;
    using System.Windows.Forms;
    using System;
    
    public static class ExtensionMethods
    {
        public static string ApplyServerURL(this SoapHttpClientProtocol service)
        {
            try
            {
                string name = service.GetType().Name;
                return string.Format("{0}{1}.svc", Settings.Instance.ServerAddress, name);
            }
            catch
            { return string.Empty; }
        }
    }
    

    现在是这样的:

    YourService us = new YourService();
    us.Url = us.ApplyServerURL();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-16
      • 1970-01-01
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多