2010-01-14 3 views
26

Я пытаюсь получить серию файлов через HTTP, используя HttpWebRequest. Первый запрос проходит через штраф, но второй раз через тот же код GetResponse() зависает и время ожидания. WireShark показывает, что HTTP-трафик не отправляется для второго запроса, поэтому, похоже, это проблема API.HttpWebRequest.GetResponse() зависает во второй раз, когда он называется

После некоторого расследования я обнаружил, что это связано с указанием длины содержимого: если я оставлю это, тогда код работает нормально.

Мой код:

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 question и this question, но в обоих случаях данный совет должен распоряжаться WebResponse, что я уже делаю.

Редактировать В ответ на Грегори, вот 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; 
} 

Edit: Оказывается, я совершил смертный грех извлекая кода из моего вопроса, что я не был проверен не связанный с проблемой. Я удалил следующие строки:

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

потому что я думал, что длина содержимого никогда не будет указана для запроса GET. Оказывается, я был неправ. Удаление этой строки устраняет проблему.

Вопрос только в том, почему? I думаю указанная длина содержимого верна, хотя возможно, что она отключена одним. Будет ли указывать слишком длинную длину содержимого, чтобы предотвратить полную загрузку и заставить соединение оставаться открытым? Я бы ожидал, что Close() и/или Dispose() должны убить соединение в любом случае.

+0

Можете ли вы пост ConfigureRequest()? – Gregory

+0

Кроме того, re: http://stackoverflow.com/questions/1386628/webrequest-getresponse-locks-up попробовали настроить значение JSkeet, чтобы упомянуть что-то более высокое, то есть 4 или 8, и посмотреть, не изменит ли это что-нибудь? – Gregory

+0

@Tim Martin: Какую строку убрали? Условие if и значение ContentLength? Таким образом, вы не устанавливаете длину контента вообще? Я попытался удалить настройку ContentLenght, но у меня все еще такая же проблема. – Ted

ответ

9

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

Повторных вызовов GetResponse вернуть тот же объект ответа; запрос не переиздан.

Update 1: Ok. Как насчет того, если вы попытаетесь закрыть webResponseStream тоже - вы в настоящее время этого не делаете, вы только закрываете webResponse (просто пытаетесь исключить ситуацию). Я бы также избавиться от HttpWebResponse тоже (не только WebResponse)

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

+0

Каждый раз круглый цикл Я вызываю WebRequest.Create (url) для создания нового запроса. –

+0

Спасибо за дополнительные предложения. Я закрываю поток (он уже был Dispose() ed), и я также обернул HttpWebResponse в блоке использования. –

+0

Я попробовал KeepAlive = false и «using» -approach, я все равно получаю ту же проблему. Похоже, что GetResponse является виновником, но проблема в том, что POST (второй запрос) вообще не отправляется (как состояния MSDN), поэтому GetResponse ждет ответа. – Ted

9
httpWebRequest.Abort(); // before you leave 

рассосется!

1

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

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

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

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

-1

«Вы должны инициализировать WebRequest и WebResponse объектов с допустимым 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 
+0

Можете ли вы объяснить, как это отвечает на вопрос? –

+0

Да, извините! У меня была та же проблема. Вам необходимо инициализировать WebRequest и WebResponse объекты с допустимой URI: запроса Dim As WebRequest = WebRequest.Create ("http://google.com") ответа Dim As WebResponse = request.GetResponse() Finaly вы необходимо закрыть объект ответа: Наконец response.Close() Надеюсь, это поможет вам: D –

0

Plase попробовать использовать:

  HttpRequestCachePolicy noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore); 
     httpWebRequest.CachePolicy = noCachePolicy; 
Смежные вопросы