System.Net.HttpWebRequest genereert verschillende WebExceptionStatus voor SSL- en niet-SSL-aanvragen onder speciale voorwaarden

Dit artikel helpt u bij het oplossen van het probleem waarbij anders WebExceptionStatus wordt gegenereerd wanneer u de System.Net.HttpWebRequest klasse gebruikt.

Oorspronkelijke productversie: .Net Framework
Origineel KB-nummer: 2007873

Symptomen

U gebruikt de System.Net.HttpWebRequest klasse van Microsoft .Net Framework om een HTTP-aanvraag (Hypertext Transfer Protocol) of Hypertext Transfer Protocol Secure (HTTPS) te verzenden naar een server. Het duurt even voordat deze aanvraag een antwoord van de server ontvangt. Als tijdens deze wachttijd de kloktijd van het systeem handmatig wordt verhoogd of als de systeemklok achterloopt en de Windows Time-service zich vervolgens aanpast aan de werkelijke lokale tijd, ondervindt u een van de volgende scenario's:

Voor een aanvraag, die is verzonden via HTTP zonder opmaak, genereert de System.Net.HttpWebRequest klasse de volgende uitzondering:

De aanvraag is afgebroken: er is een time-out opgetreden voor de bewerking.

Bovendien geeft de Status eigenschap op de gegenereerde WebException de waarde WebExceptionStatus.Timeoutaan.

Voor een aanvraag die via HTTPS is verzonden, genereert de System.Net.HttpWebRequest klasse een van de volgende uitzonderingen:

De onderliggende verbinding is gesloten: er is een onverwachte fout opgetreden bij een ontvangst.

Bovendien geeft de Status eigenschap op de gegenereerde WebException de waarde WebExceptionStatus.ReceiveFailureaan.

Of

De onderliggende verbinding is gesloten: een verbinding die naar verwachting in leven zou blijven, is gesloten door de server.

Bovendien geeft de Status eigenschap op de gegenereerde WebException de waarde WebExceptionStatus.KeepAliveFailureaan.

In alle bovenstaande scenario's heeft de, die wordt gevangen, de InnerException eigenschap. Als u de WebException eigenschap vangt en verwijst WebException.InnerException.InnerException , ziet u dat voor alle bovenstaande gevallen de tekenreeks het Message volgende aangeeft:

Een verbindingspoging is mislukt omdat de verbonden partij na een periode niet correct heeft gereageerd of omdat de verbinding is mislukt omdat de verbonden host niet heeft gereageerd.

Dit bericht is de uitgebreide interpretatie van de Winsock-foutcode 10060 = WSAETIMEDOUT.

Wanneer de systeemtijd handmatig wordt verhoogd, genereert Winsock de time-outfout 10060 correct, maar deze wordt ingepakt als verschillende uitzonderingstypen voor SSL-aanvragen (Secure Sockets Layer) en niet-SSL-aanvragen.

Onder normale time-outomstandigheden waarbij niet met de systeemtijd wordt geknoeid, geven de SSL- en niet-SSL-scenario's de WebExceptionStatus.Timeout status correct weer en wordt de algemene uitzondering gegenereerd: er is een time-out opgetreden voor de bewerking.

Oorzaak

Wanneer u de aanvraag via SSL of niet-SSL doet, wijst de klasse de System.Net.ServicePointManager aanvraag toe aan een interne verbinding, die uiteindelijk de Winsock-verbinding maakt. In het geval van SSL-aanvragen gaat deze aanvraag of verbinding via een andere interne SSL/TLS-klasse, die verantwoordelijk is voor de versleuteling of ontsleuteling van de gegevens. Voor niet-SSL-verbindingen is deze interne SSL/TLS-klasse helemaal niet betrokken.

Wanneer de tijd wordt gewijzigd en de uitzondering wordt aangetroffen op de Winsock-laag, moet deze fout nu omhoog gaan van Winsock naar de toepassingslaag. Voor niet-SSL-verbindingen wordt deze uitzondering rechtstreeks opgevangen door de interne verbindingsklasse, maar voor SSL-aanvragen wordt deze fout verwerkt door de interne SSL/TLS-klasse. Deze klasse beschouwt deze niet-SSL-fout als een ReceiveFailure of KeepAliveFailure en heeft daarom een andere uitzonderingsstatus, terwijl voor een niet-SSL-verbinding de fout correct wordt gecast omdat deze wordt verwerkt door een andere klasse.

Status

Dit gedrag is inherent aan het ontwerp van het product.

Oplossing

Om dit verschil op te lossen van de gegenereerde uitzonderingstypen onder deze speciale voorwaarde waarbij de systeemtijd wordt gemanipuleerd, moet de toepassing de WebException opvangen en vervolgens verwijzen naar de WebException.InnerException.InnerException.Message eigenschap.

Als de Message tekenreeks gelijk is aan het winsock uitgebreide foutequivalent van 10060 = WSAETIMEDOUT, kunt u de ReceiveFailure of KeepAliveFailure beschouwen als een normale time-out en niet als een ReceiveFailure of KeepAliveFailure.

De toepassing kan de onderstaande tijdelijke oplossing gebruiken bij het uitvoeren van de catch()WebException voor een Engelse versie van het framework. Voor een gelokaliseerde versie van het framework moet de onderstaande tijdelijke oplossing worden aangepast, afhankelijk van de taallokalisatie.

Belangrijk

Deze voorbeeldcode wordt geleverd als zodanig en is alleen bedoeld voor voorbeelddoeleinden. Het wordt verstrekt zonder garanties en verleent geen rechten.

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