System.Net.HttpWebRequest genera diferentes WebExceptionStatus para solicitudes SSL y no SSL en condiciones especiales
Este artículo le ayuda a resolver el problema en el que se WebExceptionStatus produce diferente al usar la System.Net.HttpWebRequest clase.
Versión del producto original: .Net Framework
Número KB original: 2007873
Síntomas
Está usando la clase de Microsoft .Net Framework para enviar una solicitud de protocolo de transferencia de hipertexto (HTTP) o protocolo de transferencia de System.Net.HttpWebRequest hipertexto seguro (HTTPS) a un servidor. Esta solicitud tarda algún tiempo en recibir una respuesta del servidor. Durante este tiempo de espera, si el tiempo de reloj del sistema aumenta manualmente o si el reloj del sistema se atrasa y, a continuación, el servicio de tiempo de Windows se ajusta a la hora local real, se experimenta uno de los siguientes escenarios:
Para una solicitud, que se envió a través de HTTP de texto sin formato, la System.Net.HttpWebRequest clase producirá la siguiente excepción:
Se ha anulado la solicitud: la operación ha quedo de espera.
Además, la Status propiedad del arrojado indicará el valor WebException WebExceptionStatus.Timeout .
Para una solicitud, que se envió a través de HTTPS, la System.Net.HttpWebRequest clase producirá una de las siguientes excepciones:
Se cerró la conexión subyacente: se produjo un error inesperado en una recepción.
Además, la Status propiedad del arrojado indicará el valor WebException WebExceptionStatus.ReceiveFailure .
O bien:
Se cerró la conexión subyacente: el servidor cerró una conexión que se esperaba mantener activa.
Además, la Status propiedad del arrojado indicará el valor WebException WebExceptionStatus.KeepAliveFailure .
En todos los escenarios anteriores, el, que se captura tiene la InnerException propiedad. Si captura la propiedad y hace referencia a la propiedad, observará que, en todos los casos WebException WebException.InnerException.InnerException anteriores, la Message cadena indicará:
Error en un intento de conexión porque la parte conectada no respondió correctamente después de un período de tiempo, o la conexión establecida falló porque el host conectado no ha respondido.
Este mensaje es la interpretación detallada del código de error winsock 10060 = WSAETIMEDOUT.
Por lo tanto, cuando se aumenta manualmente el tiempo del sistema, Winsock genera correctamente el error de tiempo de espera 10060, pero se ajusta como tipos de excepción diferentes para las solicitudes ssl y no SSL.
En circunstancias de tiempo de espera normales en las que el tiempo del sistema no se ha alterado, los escenarios SSL y no SSL reflejarán correctamente el estado y producirán la excepción común: la operación ha agotado el tiempo de WebExceptionStatus.Timeout espera.
Causa
Cuando realice la solicitud a través de SSL o que no sea SSL, la clase asignará la solicitud a una conexión interna, que finalmente realizará la conexión System.Net.ServicePointManager Winsock. En el caso de las solicitudes SSL, esta solicitud o conexión pasa a través de otra clase SSL/TLS interna, que es responsable del cifrado o descifrado de los datos. Para las conexiones que no son SSL, esta clase SSL/TLS interna no está implicada en absoluto.
Cuando se modifica el tiempo y se encuentra la excepción en la capa Winsock, este error ahora debe desplazarse hacia arriba desde Winsock a la capa de aplicación. Para las conexiones que no son SSL, la clase de conexión interna detecta esta excepción directamente, pero para las solicitudes SSL, este error lo controla la clase SSL/TLS interna. Esta clase considera este error que no es SSL como un estado de excepción o, por lo tanto, tiene un estado de excepción diferente, mientras que para la conexión que no es SSL, el error se convierte correctamente, ya que lo controla una ReceiveFailure KeepAliveFailure clase diferente.
Estado
Este comportamiento es una característica del diseño de la aplicación.
Resolución
Para resolver esta discrepancia de los tipos de excepción que se inician en esta condición especial en la que se manipula el tiempo del sistema, la aplicación debe capturar la propiedad y, a continuación, hacer referencia a WebException WebException.InnerException.InnerException.Message la propiedad.
Si la cadena es igual al equivalente de error detallado winsock de Message 10060 = WSAETIMEDOUT, puede considerar o como un tiempo de espera normal y no considerarlo como un o ReceiveFailure KeepAliveFailure ReceiveFailure KeepAliveFailure .
La aplicación puede usar la siguiente solución alternativa al realizar el catch() de para una versión en inglés del WebException marco. Para una versión localizada del marco, la siguiente solución alternativa debe ajustarse en función de la localización del idioma.
Importante
Este código de ejemplo se proporciona tal como está y está diseñado únicamente para fines de ejemplo. Se proporciona sin garantías y no otorga derechos.
try
{
......
}
catch (WebException oWEx)
{
WebExceptionStatus oStatus = oWEx.Status;
String strTimeoutErrorMessage = "A connection attempt failed because the connected party did not properly respond "
+ "after a period of time, or established connection failed because connected host has failed to respond";
switch (oStatus)
{
case WebExceptionStatus.KeepAliveFailure:
if ((oWEx.InnerException != null) && (oWEx.InnerException.InnerException != null)
&& oWEx.InnerException.InnerException.Message.ToString().Equals(strTimeoutErrorMessage, StringComparison.CurrentCultureIgnoreCase))
{ //----------------------------------------------------------------------
// This is Timeout Error which is wrongly thrown as a ReceiveFailure for
// SSL requests under this special condition.
//
// Handle this as a Timeout Error
//----------------------------------------------------------------------
}
else
{
//----------------------------------------------------------------------
// This is truly a KeepAliveFailure.
//----------------------------------------------------------------------
}
break;
case WebExceptionStatus.Timeout:
//----------------------------------------------------------------------
// This is a Timeout.
//----------------------------------------------------------------------
break;
case WebExceptionStatus.ReceiveFailure:
if ((oWEx.InnerException != null)
&& (oWEx.InnerException.InnerException != null)
&& oWEx.InnerException.InnerException.Message.ToString ().Equals (strTimeoutErrorMessage, StringComparison.CurrentCultureIgnoreCase))
{ //----------------------------------------------------------------------
// This is Timeout Error which is wrongly thrown as a ReceiveFailure for
// SSL requests under this special condition.
//
// Handle this as a Timeout Error
//----------------------------------------------------------------------
}
else
{ //----------------------------------------------------------------------
// This is truly a ReceiveFailure.
//----------------------------------------------------------------------
}
break;
default:
//----------------------------------------------------------------------
// This is some other Exception
//----------------------------------------------------------------------
break;
}
}