HttpWebRequest.GetResponse()在第二次调用时挂起

时间:2010-01-14 12:17:53

标签: c# .net httpwebrequest

我正在尝试使用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请求指定内容长度。事实证明我错了。删除此行可以解决问题。

我现在唯一的问题是为什么?我认为指定的内容长度是正确的,尽管它可能是一个。指定内容长度太短会阻止完整下载并导致连接保持打开状态?我原以为Close()和/或Dispose()应该终止连接。

5 个答案:

答案 0 :(得分:10)

httpWebRequest.Abort(); // before you leave

会解决!

查看resource

答案 1 :(得分:8)

确保每次都创建一个新的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
- 我没有配置中的连接管理内容(我不循环来发出一系列请求)

答案 2 :(得分:1)

HttpWebRequest.ContentLength的文档说:

  

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

     

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

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

答案 3 :(得分:0)

尝试使用:

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

答案 4 :(得分:-1)

'您需要使用有效的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