HttpWebRequest.GetResponse () зависает при втором вызове - PullRequest
26 голосов
/ 14 января 2010

Я пытаюсь получить серию файлов через HTTP, используя HttpWebRequest. Первый запрос проходит нормально, но второй раз через тот же код 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();
}

Симптомы кажутся очень похожими на этот вопрос и этот вопрос , но в обоих случаях дается совет избавиться от 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 ]

10 голосов
/ 31 мая 2013
httpWebRequest.Abort(); // before you leave

Решит!

Взгляните на ресурс .

8 голосов
/ 14 января 2010

Убедитесь, что вы создаете НОВЫЙ запрос HttpWebRequest каждый раз. Цитата из ссылки на MSDN GetResponse метод:

Несколько вызовов на 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
- У меня нет настроек управления соединением (я не зацикливаюсь, чтобы сделать серию запросов)

1 голос
/ 31 мая 2013

Документация для HttpWebRequest.ContentLength говорит:

Любое значение, отличное от -1 в свойстве ContentLength, указывает на то, что запрос загружает данные и что только методы, которые загружают данные, могут быть установлены в свойстве Method.

После того как для свойства ContentLength установлено значение, это число байтов должно быть записано в поток запроса, который возвращается путем вызова метода GetRequestStream или обоих методов BeginGetRequestStream и EndGetRequestStream.

Я подозреваю, что это зависает, потому что вы устанавливаете длину контента, но не загружаете никаких данных. Можно было бы подумать, что в этом случае он должен вызвать исключение, но, по-видимому, это не так.

0 голосов
/ 04 января 2017

Пожалуйста, попробуйте использовать:

         HttpRequestCachePolicy noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
         httpWebRequest.CachePolicy = noCachePolicy;
0 голосов
/ 05 марта 2015

'Вам необходимо инициализировать объекты веб-запроса и веб-ответа с действительным URI:

        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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...