2010-01-14 23 views
26

Estoy tratando de buscar una serie de archivos a través de HTTP, utilizando HttpWebRequest. La primera solicitud pasa bien, pero la segunda vez a través del mismo código GetResponse() se cuelga y se agota. WireShark muestra que no se envía tráfico HTTP para la segunda solicitud, por lo que parece que se trata de un problema de API.HttpWebRequest.GetResponse() se cuelga la segunda vez que se llama

Después de algunas investigaciones, descubrí que tiene que ver con la especificación de la longitud del contenido: si lo dejo, el código funciona bien.

Mi código es:

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(); 
} 

Los síntomas parecen muy similares a this question y this question, pero en ambos casos el consejo dado es disponer de la WebResponse, que ya estoy haciendo.

Editar En respuesta a Gregory, aquí es 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; 
} 

Editar: Resulta que he cometido el pecado capital de código de eliminar de mi pregunta que no había verificado era no relacionado con el problema. Había eliminado las siguientes líneas:

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

porque pensé que la longitud del contenido nunca se especificaría para una solicitud GET. Resulta que estaba equivocado. Eliminar esta línea soluciona el problema.

La única pregunta que tengo ahora es ¿por qué? I piensa que la longitud del contenido que se especifica es correcta, aunque es posible que esté desactivada en uno. ¿La especificación de una longitud de contenido demasiado corta impide que se realice la descarga completa y hace que la conexión se deje abierta? Hubiera esperado que Close() y/o Dispose() deberían matar la conexión de todos modos.

+0

Se puede publicar ConfigureRequest()? – Gregory

+0

Además, re: http://stackoverflow.com/questions/1386628/webrequest-getresponse-locks-up ¿ha intentado configurar el valor que JSkeet menciona a algo más alto, es decir, 4 u 8, y ver si esto cambia algo? – Gregory

+0

@Tim Martin: ¿Qué línea eliminaste? ¿La cláusula if y la configuración de ContentLength? Entonces, ¿no establece la duración del contenido en absoluto? Traté de eliminar la configuración de ContentLenght, pero todavía tengo el mismo problema. – Ted

Respuesta

9

Asegúrese de crear una nueva HttpWebRequest cada vez. Presupuesto de la referencia MSDN en GetResponse método:

múltiples llamadas a GetResponse vuelven el mismo objeto de respuesta; la solicitud no se vuelve a emitir.

Actualización 1: Ok. ¿Qué tal si también intentas cerrar el webResponseStream? Actualmente no lo haces, solo estás cerrando la respuesta web (solo intentamos descartar las cosas). También me gustaría disponer de la HttpWebResponse también (no sólo el WebResponse)

Actualización 2: La única otra cosa que puedo sugerir es tener un vistazo a los siguientes artículos que miré cuando hice algo similar a lo que está haciendo:
http://arnosoftwaredev.blogspot.com/2006/09/net-20-httpwebrequestkeepalive-and.html
http://www.devnewsgroups.net/dotnetframework/t10805-exception-with-httpwebrequest-getresponse.aspx

Las únicas cosas notables que hago diferente son:
- establecer WebRequest.KeepAlive = false
- No tengo la materia de gestión de conexión en la configuración (no me bucle de vuelta para hacer una serie de peticiones)

+0

Cada vez redonda el ciclo al que estoy llamando WebRequest.Create (url) para crear una nueva solicitud. –

+0

Gracias por las sugerencias adicionales. Ahora estoy cerrando la transmisión (ya estaba siendo Dispose() ed), y también he envuelto la HttpWebResponse en un bloque de uso también. –

+0

He intentado con KeepAlive = false y el método "using", sigo teniendo el mismo problema. Parece que GetResponse es el culpable, pero el problema es que el POST (la segunda solicitud) no se envía en absoluto (como los estados de MSDN), por lo tanto, el GetResponse está esperando una respuesta. – Ted

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

resolverá!

1

Documentación para HttpWebRequest.ContentLength dice:

Cualquier valor distinto de -1 en la propiedad ContentLength indica que los datos de solicitud de archivos y que los únicos métodos que la carga de datos se les permite ser establecido en la propiedad Método.

Después de establecer la propiedad ContentLength en un valor, ese número de bytes se debe escribir en la secuencia de solicitud que se devuelve llamando al método GetRequestStream o los métodos BeginGetRequestStream y EndGetRequestStream.

Sospecho que se cuelga porque está configurando la longitud del contenido pero luego no carga ningún dato. Uno podría pensar que debería lanzar una excepción en ese caso, pero aparentemente no es así.

-1

'Es necesario inicializar los objetos de WebRequest y WebResponse con un URI válido:

 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

¿Puedes explicarnos cómo responde esto a la pregunta? –

+0

Sí, lo siento! Tuve el mismo problema. Es necesario inicializar los objetos de WebRequest y WebResponse con un URI válido: solicitud Dim Como WebRequest = WebRequest.Create ("http://google.com") respuesta Dim Como WebResponse = request.GetResponse() Finaly se debe cerrar el objeto de respuesta: Por último response.Close() Espero que lo ayude: D –

0

Plase intente uso:

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