使用Connection:关闭webserver SOAP请求

时间:2014-05-07 16:28:48

标签: web-services wcf http soap .net-4.0

  

底层连接已关闭:服务器已关闭预期保持活动状态的连接。

使用.Net 4.0 Web服务客户端与ONVIF网络设备进行通信时,我们经常会遇到此异常。

查看packet captures,这似乎是一个不符合HTTP规范并在发送响应后关闭连接的设备,而HTTP/1.1默认保持活动状态。 这导致客户端(WCF)在服务器刚刚关闭它时尝试重用连接,

在制造商解决这个问题之前,有什么办法可以告诉Web服务/ SOAP客户端不要使用持久连接吗?

请注意,修改标头以使用Connection: Close不会有帮助,除非它正在关闭,但SOAP客户端希望它保持打开状态。

2 个答案:

答案 0 :(得分:2)

  

但有什么办法可以告诉Web服务/ SOAP客户端不要使用持久连接吗?

,您可以将InstanceContextMode设置为PerCall,它会创建新的InstanceContext对象,然后在每次调用之后创建并回收。

换句话说,当我们按照调用配置WCF服务时,会为通过WCF代理客户端进行的每个方法调用创建新的服务实例。

您可以像以下一样使用它:

  • ServiceBehavior上设置合同接口实施,如:

    [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)] public class CalculatorService : ICalculator { ... }

更新 -

根据您的评论,似乎解决方案是明确将KeepAlive属性设置为FALSE

可以通过多种方式完成:

  1. IIS设置
  2. 的Web.config
  3. <强>代码

    我实际上不知道你对代码有多少控制权。但是在你正在消费服务的客户端,我们可以改变这种行为,如:

    protected override System.Net.WebRequest GetWebRequest(Uri uri)
    {
        System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)base.GetWebRequest(uri);
        webRequest.KeepAlive = false;
        return webRequest;
    }
    

    namespace YourNamespace
    {
        using System.Diagnostics;
        using System.Web.Services;
        using System.ComponentModel;
        using System.Web.Services.Protocols;
        using System;
        using System.Xml.Serialization;
        /// <summary>
        /// This partial class makes it so all requests specify
        /// "Connection: Close" instead of "Connection: KeepAlive" in the HTTP headers.
        /// </summary>
        public partial class YourServiceNameWse : Microsoft.Web.Services3.WebServicesClientProtocol
        {
            protected override System.Net.WebRequest GetWebRequest(Uri uri)
            {
                System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)base.GetWebRequest(uri);
                webRequest.KeepAlive = false;
                return webRequest;
            }
        }
    }
    

    IIS设置

    1. 打开Internet信息服务(IIS)管理器:
    2. 如果您使用的是Windows Server 2008或Windows Server 2008 R2:
      • 在任务栏上,单击“开始”,指向“管理工具”,然后单击“Internet信息服务(IIS)管理器”。
      • 如果您使用的是Windows Vista或Windows 7:    在任务栏上,单击“开始”,然后单击“控制面板”。
      • 双击“管理工具”,然后双击“Internet信息服务(IIS)管理器”。
      • 在“连接”窗格中,转到要为其启用HTTP保持活动的站点,应用程序或目录。
      • 在“主页”窗格中,双击“HTTP响应标头”。
      • 在“HTTP响应标头”窗格中,单击“操作”窗格中的“设置公共标题...”。
      • 在“设置常见HTTP响应标头”对话框中,取消选中该框以禁用HTTP保持活动,然后单击“确定”。
    3. 此外,您可以使用 CommandLine 设置IIS上的特定网站,如:

      appcmd.exe set config "<Your Web Site Here>" -section:system.webServer/httpProtocol /allowKeepAlive:"False"
      

      <强>的Web.Config

      <configuration>
         <system.webServer>
            <httpProtocol allowKeepAlive="false" />
         </system.webServer>
      </configuration>
      

      我希望它能以某种方式帮助你。

答案 1 :(得分:1)

底层HttpWebRequest是在生成的客户端类使用的HttpChannelFactory中创建的。 这是从公开HttpTransportBindingElement属性的KeepAliveEnabled创建的。

绑定元素是在WSHttpBinding类内部创建的,可以通过覆盖GetTransport()来更改。

private class WSHttpBindingNoKeepAlive : WSHttpBinding {
    public WSHttpBindingNoKeepAlive(SecurityMode securityMode)
        : base(securityMode) {
    }

    protected override TransportBindingElement GetTransport() {
        TransportBindingElement transport = base.GetTransport();
        if (transport is HttpTransportBindingElement) {
            ((HttpTransportBindingElement)transport).KeepAliveEnabled = false;
        }
        return transport;
    }
}

然后可以使用此覆盖...Binding类,如:

WSHttpBindingNoKeepAlive clientBinding = new WSHttpBindingNoKeepAlive(SecurityMode.None);
EndpointAddress address = new EndpointAddress(this.deviceUrl);
WSNameSpace.WSClient client = new WSNameSpace.WSClient(clientBinding, address);