System.Net.HttpWebRequest löst verschiedene WebExceptionStatus für SSL- und Nicht-SSL-Anforderungen unter bestimmten Bedingungen aus.

Dieser Artikel hilft Ihnen, das Problem zu beheben, bei dem bei Verwendung der Klasse unterschiedliche WebExceptionStatus Fehler ausgelöst System.Net.HttpWebRequest werden.

Ursprüngliche Produktversion:   .Net Framework
Ursprüngliche KB-Nummer:   2007873

Problembeschreibung

Sie verwenden die System.Net.HttpWebRequest Klasse von Microsoft .Net Framework, um eine Hypertext Transfer Protocol (HTTP)- oder Hypertext Transfer Protocol Secure (HTTPS)-Anforderung an einen Server zu senden. Diese Anforderung nimmt einige Zeit in Anspruch, um eine Antwort vom Server zu erhalten. Wenn die Systemuhrzeit während dieser Wartezeit manuell erhöht wird oder die Systemuhr zurückliegt und sich der Windows-Zeitdienst an die tatsächliche Ortszeit anpasst, wird eines der folgenden Szenarien auftreten:

Bei einer Anforderung, die über Nur-Text-HTTP gesendet wurde, löst die System.Net.HttpWebRequest Klasse die folgende Ausnahme aus:

Die Anforderung wurde abgebrochen: Für den Vorgang ist ein Timeout aufgetreten.

Darüber hinaus gibt die Status Eigenschaft für den ausgelösten Wert WebException WebExceptionStatus.Timeout an.

Für eine Anforderung, die über HTTPS gesendet wurde, löst die System.Net.HttpWebRequest Klasse eine der folgenden Ausnahmen aus:

Die zugrunde liegende Verbindung wurde geschlossen: Bei einem Empfang ist ein unerwarteter Fehler aufgetreten.

Darüber hinaus gibt die Status Eigenschaft für den ausgelösten Wert WebException WebExceptionStatus.ReceiveFailure an.

Oder:

Die zugrunde liegende Verbindung wurde geschlossen: Eine Verbindung, die am Leben gehalten werden sollte, wurde vom Server geschlossen.

Darüber hinaus gibt die Status Eigenschaft für den ausgelösten Wert WebException WebExceptionStatus.KeepAliveFailure an.

In allen oben genannten Szenarien hat das abgefangene Element die InnerException Eigenschaft. Wenn Sie die Eigenschaft abfangen WebException und auf diese WebException.InnerException.InnerException verweisen, werden Sie feststellen, dass die Zeichenfolge für alle oben genannten Fälle Message Folgendes angibt:

Ein Verbindungsversuch ist fehlgeschlagen, weil die verbundene Partei nach einem bestimmten Zeitraum nicht ordnungsgemäß reagiert hat, oder die hergestellte Verbindung ist fehlgeschlagen, da der verbundene Host nicht reagiert hat.

Diese Meldung ist die ausführliche Interpretation des Winsock-Fehlercodes 10060 = WSAETIMEDOUT.

Wenn die Systemzeit also manuell erhöht wird, löst Winsock den Timeoutfehler 10060 ordnungsgemäß aus, wird aber als unterschiedliche Ausnahmetypen für SSL-Anforderungen (Secure Sockets Layer) und Nicht-SSL-Anforderungen umbrochen.

Unter normalen Timeout-Situationen, in denen die Systemzeit nicht manipuliert wird, spiegeln die SSL- und Nicht-SSL-Szenarien den Status korrekt wider WebExceptionStatus.Timeout und lösen die allgemeine Ausnahme aus: Der Vorgang hat einen Timeout.

Ursache

Wenn Sie die Anforderung über SSL oder Nicht-SSL stellen, weist die System.Net.ServicePointManager Klasse die Anforderung einer internen Verbindung zu, die schließlich die Winsock-Verbindung herstellen wird. Bei SSL-Anforderungen durchläuft diese Anforderung oder Verbindung eine andere interne SSL/TLS-Klasse, die für die Verschlüsselung oder Entschlüsselung der Daten verantwortlich ist. Bei Nicht-SSL-Verbindungen ist diese interne SSL/TLS-Klasse überhaupt nicht beteiligt.

Wenn der Zeitpunkt geändert wird und die Ausnahme auf der Winsock-Ebene auftritt, muss dieser Fehler jetzt von Winsock zur Anwendungsebene nach oben verschoben werden. Bei Nicht-SSL-Verbindungen wird diese Ausnahme direkt von der internen Verbindungsklasse abgefangen, bei SSL-Anforderungen wird dieser Fehler jedoch von der internen SSL/TLS-Klasse behandelt. Diese Klasse betrachtet diesen Nicht-SSL-Fehler als einen ReceiveFailure oder hat daher einen anderen KeepAliveFailure Ausnahmestatus, während bei Nicht-SSL-Verbindungen der Fehler korrekt umgewandelt wird, da er von einer anderen Klasse behandelt wird.

Status

Es handelt sich hierbei um ein beabsichtigtes Verhalten.

Lösung

Um diese Abweichung der ausgelösten Ausnahmetypen unter dieser speziellen Bedingung zu beheben, in der die Systemzeit manipuliert wird, muss die Anwendung die Eigenschaft abfangen WebException und dann auf die Eigenschaft WebException.InnerException.InnerException.Message verweisen.

Wenn die Message Zeichenfolge dem ausführlichen Winsock-Fehlerentsprechung 10060 = WSAETIMEDOUT entspricht, können Sie das ReceiveFailure Oder als KeepAliveFailure reguläres Timeout und nicht als ein ReceiveFailure oder KeepAliveFailure betrachten.

Die Anwendung kann die nachstehende Problemumgehung beim Ausführen catch() der für eine englische Version des WebException Frameworks verwenden. Bei einer lokalisierten Version des Frameworks muss die folgende Problemumgehung je nach Sprachlokalisierung angepasst werden.

Wichtig

Dieser Beispielcode wird in der vorliegenden Form bereitgestellt und ist nur für Beispielzwecke vorgesehen. Es wird ohne Gewährleistungen bereitgestellt und gewährt keine Rechte.

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