【问题标题】:HttpWebRequest.GetResponse() hangs the second time it is calledHttpWebRequest.GetResponse() 在第二次被调用时挂起
【发布时间】:2010-01-14 12:17:52
【问题描述】:

我正在尝试使用 HttpWebRequest 通过 HTTP 获取一系列文件。第一个请求通过正常,但第二次通过相同的代码 GetResponse() 挂起并超时。 WireShark 显示没有为第二个请求发送 HTTP 流量,因此看起来这是一个 API 问题。

经过一番调查,我发现它与指定内容长度有关:如果我忽略它,那么代码可以正常工作。

我的代码是:

HttpWebRequest  httpWebRequest = ConfigureRequest();

using (WebResponse webResponse = httpWebRequest.GetResponse())
    // On the second iteration we never get beyond this line
{
    HttpWebResponse httpWebResponse = webResponse as HttpWebResponse;

    using (Stream webResponseStream = httpWebResponse.GetResponseStream())
    {
        if (webResponseStream != null)
        {
            // Read the stream
        }
    }

    statusCode = httpWebResponse.StatusCode;
    httpWebResponse.Close();
}

症状似乎与 this questionthis question 非常相似,但在这两种情况下,给出的建议都是处理 WebResponse,我已经在这样做了。

编辑响应 Gregory,这里是 ConfigureRequest():

private HttpWebRequest ConfigureRequest()
{
    string          sUrl            = CreateURL(bucket, key);
    HttpWebRequest  httpWebRequest  = WebRequest.Create(sUrl) as HttpWebRequest;

    httpWebRequest.AllowWriteStreamBuffering = false;
    httpWebRequest.AllowAutoRedirect = true;
    httpWebRequest.UserAgent = this.m_sUserAgent;
    httpWebRequest.Method = "GET";
    httpWebRequest.Timeout = this.m_iTimeout;

    // *** NB: This line was left out of my original posting, and turned out to be
    // crucial
    if (m_contentLength > 0)
        httpWebRequest.ContentLength = m_contentLength;

    httpWebRequest.Headers.Add(StaticValues.Amazon_AlternativeDateHeader, timestamp);
    httpWebRequest.Headers.Add(StaticValues.HttpRequestHeader_Authorization, StaticValues.Amazon_AWS + " " + aWSAccessKeyId + ":" + signature);

    return httpWebRequest;
}

编辑:事实证明,我犯了从我的问题中删除我没有验证的与问题无关的代码的大罪。我删除了以下几行:

    if (m_contentLength > 0)
        httpWebRequest.ContentLength = m_contentLength;

因为我认为永远不会为 GET 请求指定内容长度。事实证明我错了。删除此行可以解决问题。

我现在唯一的问题是为什么?我认为指定的内容长度是正确的,尽管它可能会偏离 1。指定过短的内容长度会阻止完全下载并导致连接保持打开状态吗?我本来希望 Close() 和/或 Dispose() 无论如何都应该终止连接。

【问题讨论】:

  • 你能发布 ConfigureRequest() 吗?
  • 另外,回复:stackoverflow.com/questions/1386628/… 您是否尝试过将 JSkeet 提到的值配置为更高的值,即 4 或 8,看看这是否会改变什么?
  • @Tim Martin:你删除了哪一行? if 子句和 ContentLength 的设置?所以你根本不设置内容长度?我尝试删除 ContentLenght 的设置,但我仍然遇到同样的问题。
  • 我遇到了类似的问题。这解决了我的问题:stackoverflow.com/questions/15181050/…

标签: c# .net httpwebrequest


【解决方案1】:
httpWebRequest.Abort(); // before you leave

会解决的!

看看resource

【讨论】:

  • 有没有机会获得更多关于为什么这行得通的信息?我一直在努力寻找未处理的WebHttpResponse 对象,但没有运气。您的解决方案已解决了问题 - 但为什么呢?
  • @DavidPoxon 伙计,我遇到了同样的问题,调用这个方法就是答案,但我不记得情况了......看看这个resource
  • @DavidPoxon 他们使用TimeoutCallback 在请求超时时调用Abort
【解决方案2】:

确保您每次都创建一个新的 HttpWebRequest。引用 GetResponse 方法的 MSDN 参考:

多次调用 GetResponse 返回 相同的响应对象;请求 不会重新发行。

更新 1: 好的。如果您也尝试关闭 webResponseStream 怎么样 - 您目前不这样做,您只是关闭 webResponse(只是试图排除事情)。我也会处理 httpWebResponse(不仅仅是 WebResponse)

更新 2: 我唯一可以建议的另一件事是查看以下文章,这些文章是我在做类似于您正在做的事情时看到的:
http://arnosoftwaredev.blogspot.com/2006/09/net-20-httpwebrequestkeepalive-and.html
http://www.devnewsgroups.net/dotnetframework/t10805-exception-with-httpwebrequest-getresponse.aspx

我所做的唯一不同之处在于:
- 设置 webrequest.KeepAlive = false
- 我在配置中没有连接管理的东西(我没有循环发出一系列请求)

【讨论】:

  • 每次循环我都会调用 WebRequest.Create(url) 来创建一个新请求。
  • 感谢其他建议。我现在正在关闭流(它已经被 Dispose()ed),并且我也将 HttpWebResponse 包装在 using 块中。
  • 我已经尝试过 KeepAlive=false 和“使用”-方法,我仍然遇到同样的问题。看起来 GetResponse 是罪魁祸首,但问题是根本没有发送 POST(第二个请求)(如 MSDN 所述),因此 GetResponse 正在等待答案。
【解决方案3】:

HttpWebRequest.ContentLength 的文档说:

ContentLength 属性中除-1 以外的任何值表示请求上传数据,并且仅允许在 Method 属性中设置上传数据的方法。

ContentLength 属性设置为一个值后,该字节数必须写入通过调用 GetRequestStream 方法或同时调用 BeginGetRequestStream 和 EndGetRequestStream 方法返回的请求流。

我怀疑它挂起是因为您正在设置内容长度但没有上传任何数据。有人会认为在这种情况下它应该抛出异常,但显然它不会。

【讨论】:

    【解决方案4】:

    请尝试使用:

             HttpRequestCachePolicy noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
             httpWebRequest.CachePolicy = noCachePolicy;
    

    【讨论】:

      【解决方案5】:

      '你需要用一个有效的URI来初始化webrequest和webresponse对象:

              Dim request As WebRequest = WebRequest.Create("http://google.com")
              Dim response As WebResponse = request.GetResponse()
      
              Function UrlExists(ByVal URL As String) As Boolean
                  Try
                      request = WebRequest.Create(URL)
                      response = request.GetResponse()
                  Catch ex As Exception
                      Return False
                  Finally
                      response.Close()
                  End Try
                  Return True
              End Function
      

      【讨论】:

      • 你能解释一下这是如何回答这个问题的吗?
      • 是的,对不起!我有同样的问题。您需要使用有效的 URI 初始化 webrequest 和 webresponse 对象: Dim request As WebRequest = WebRequest.Create("google.com") Dim response As WebResponse = request.GetResponse() 最后您需要关闭响应对象: 最后响应。 Close() 希望对你有帮助 :D
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-03
      • 1970-01-01
      • 1970-01-01
      • 2018-06-15
      相关资源
      最近更新 更多