c# - httpWebRequest(底层连接已关闭 : The connection was closed unexpectedly. )

标签 c# httpwebrequest fiddler connectionexception

我正在开发一个 C# 应用程序,它记录来自网络服务器的数据。它向网络服务器发送以下发布请求并等待响应。

    /// <summary>
    /// Function for obtaining testCgi data 
    /// </summary>
    /// <param name="Parameters"></param>
    /// <returns></returns>
    private string HttpmyPost(string Parameters)
    {
        string str = "No response";
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriTestCGI);
        request.Method = "POST";

        byte[] bytes = Encoding.UTF8.GetBytes(Parameters);
        request.ContentLength = bytes.Length;

        Stream requestStream = request.GetRequestStream();
        requestStream.Write(bytes, 0, bytes.Length);
        requestStream.Close();

            WebResponse response = request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader reader = new StreamReader(stream);

            try
            {
                var result = reader.ReadToEnd();
            stream.Dispose();
            str = result.ToString();
            reader.Dispose();
        }
        catch (WebException ex)
        {
            //System.Windows.Forms.MessageBox.Show(ex.Message);
            System.Diagnostics.Trace.WriteLine(ex.Message);

        }
        finally
        {
            request.Abort();
        }
        return str;
    }

我遇到了错误

> "The underlying connection was closed: The connection was closed
> unexpectedly"

我已尝试调试错误,并使用 fiddler 来检查 Firefox 给出的发布请求。令我惊讶的是,每当 Fiddler 运行时,我的程序都能完美运行。当我关闭 fiddler 时,我遇到了同样的错误。

我怀疑由于 Fiddler 充当代理,它可能会更改某些设置。 我试过使用 webclient,结果是一样的。

当我尝试用 python 编写请求时,一切正常,没有任何问题。当然,我可以选择安装 IronPython 并包装该特定功能,但我认为这有点矫枉过正且缺乏优雅,因此我正在寻求一种更精简的方法。我怀疑这只不过是一次设置调整。

我已经尝试过修改,在我的情况下它是无关紧要的。

request.Accept 
request.ReadWriteTimeout 
request.Timeout 
request.UserAgent 
request.Headers
request.AutomaticDecompression 
request.Referer
request.AllowAutoRedirect
//request.TransferEncoding 
request.Expect
request.ServicePoint.Expect100Continue 
request.PreAuthenticate 
request.KeepAlive 
request.ProtocolVersion 
request.ContentType

无论是否进行上述调整,当 Fiddler 捕获数据时,代码都能正常工作。

另外值得注意的是,程序在

处产生了错误
WebResponse response = request.GetResponse();

更新: 按照@EricLaw 的建议,我研究了延迟。 我找到了这篇文章 HttpWebRequest gets slower when adding an Interval 这建议转向 Nagle 算法。 现在没有关闭的连接,尽管整体响应有一点延迟(当我使用 winforms 而不是异步时)。

最佳答案

我在这里写了一些关于 Fiddler 如何“神奇地”修复问题的文章:http://blogs.telerik.com/fiddler/posts/13-02-28/help!-running-fiddler-fixes-my-app-

您遇到的问题实际上是 .NET Framework 本身的错误。 HTTP 的规则是服务器可以在发送第一个响应后随时关闭 KeepAlive 连接(例如,它不需要接受连接上的另一个请求,即使客户端请求 KeepAlive 行为)。

.NET 有一个 bug,如果它在响应完成后关闭连接,它期望服务器将包含一个 Connection: close 响应 header 。如果服务器在没有 Connection: Close header (根据 RFC2616 完全有效)的情况下关闭连接,.NET 将在尝试发送连接上的下一个请求时遇到已关闭的连接,并且会抛出此异常。 .NET 应该做的是默默地创建一个新连接并在该新连接上重新发送请求。

Fiddler 解决了这个问题,因为它不关心服务器是否关闭连接,它会保持与客户端的连接。当客户端发送第二个请求时,Fiddler 尝试重用它与服务器的连接,注意到它已关闭,并静默创建一个新连接。

您可以通过以下方式在您的代码中缓解此问题:

  1. 根据请求禁用 keepalive(这会影响性能)
  2. 捕获异常并自动重试
  3. 更改服务器以保持连接更长时间

方法 #3 仅在您控制服务器时才有效,并且由于客户端可能位于网关/代理后面,网关/代理在使用后关闭连接,因此您也应该使用方法 #2。

关于c# - httpWebRequest(底层连接已关闭 : The connection was closed unexpectedly. ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21481682/

相关文章:

c# - ForEach lambda 异步与 Task.WhenAll

xcode - 快速网络请求未提交(使用alamofire)

elasticsearch - NEST 1.0:请参阅Fiddler的要求

request - 如何在 Fiddler 中生成分块请求?

c# - 如何根据动态字段名引用 Linq 中的字段

c# - MS 图表数据值标签

c# - 如何控制 DateTimePicker 中的时间间隔

c# - Web 请求/上传在最后失败

asp.net - 捕获httpwebrequest超时后如何关闭底层连接

ssl - Fiddler:我可以禁用 SSL session 重新协商吗