基础连接已关闭:接收时发生意外错误。
此外, Status 引发 WebException 的 上的 属性将指示值 WebExceptionStatus.ReceiveFailure。
或
基础连接已关闭:服务器关闭了预期保持活动状态的连接。
此外, Status 引发 WebException 的 上的 属性将指示值 WebExceptionStatus.KeepAliveFailure。
在上述所有方案中, 捕获的 具有 InnerException 属性。 如果捕获 WebException 并引用 属性 WebException.InnerException.InnerException ,你会注意到,对于上述所有情况, Message 字符串将指示:
连接尝试失败,因为连接方在一段时间后没有正确响应,或者由于连接的主机无法响应而建立连接失败。
此消息是 Winsock 错误代码 10060 = WSAETIMEDOUT 的详细解释。
因此,当手动增加系统时间时,Winsock 会正确引发超时错误 10060,但安全套接字层 (SSL) 和非 SSL 请求的不同异常类型会被包装。
在系统时间未篡改的正常超时情况下,SSL 和非 SSL 方案将正确反映 WebExceptionStatus.Timeout 状态并引发常见异常: 操作已超时。
原因
通过 SSL 或非 SSL 发出请求时, System.Net.ServicePointManager 类会将请求分配给内部连接,该连接最终将建立 Winsock 连接。 对于 SSL 请求,此请求或连接通过另一个内部 SSL/TLS 类,该类负责加密或解密数据。 对于非 SSL 连接,根本不涉及此内部 SSL/TLS 类。
修改时间并在 Winsock 层遇到异常时,此错误现在需要从 Winsock 向上传播到应用层。 对于非 SSL 连接,内部连接类直接捕获此异常,但对于 SSL 请求,此错误由内部 SSL/TLS 类处理。 此类将此非 SSL 错误视为 ReceiveFailure 或 KeepAliveFailure ,因此具有不同的异常状态,而对于非 SSL 连接,错误被正确强制转换,因为它由其他类处理。
状态
此行为是设计使然。
解决方案
为了解决在此特殊情况下引发的异常类型的这种差异,其中系统时间被篡改,应用程序需要捕获 WebException ,然后引用 属性 WebException.InnerException.InnerException.Message 。
Message如果字符串等于等效于 10060 = WSAETIMEDOUT 的 winsock 详细错误,则可以将 ReceiveFailure 或 KeepAliveFailure 视为常规超时,而不将其视为 ReceiveFailure 或 KeepAliveFailure。
对于框架的英语版本,应用程序可以在执行 catch() 的 WebException 时使用以下解决方法。 对于框架的本地化版本,需要根据语言本地化调整以下解决方法。
重要
此示例代码按原样提供,仅用于示例目的。 不提供任何保证,也不授予任何权利。
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;
}
}