Portieren von WinINet-Anwendungen zu WinHTTP

Microsoft Windows HTTP Services (WinHTTP) richtet sich an Middle-Tier- und Back-End-Serveranwendungen, die Zugriff auf einen HTTP-Clientstapel erfordern. Microsoft Windows Internet (WinINet) bietet einen HTTP-Clientstapel für Clientanwendungen sowie Zugriff auf die Protokolle FTP (File Transfer Protocol), SOCKSv4 und Gopher. Anhand dieser Übersicht können Sie ermitteln, ob die Portierung Ihrer WinINet-Anwendungen zu WinHTTP von Vorteil wäre. Außerdem werden spezifische Konvertierungsanforderungen beschrieben.

Wichtige Punkte vor dem Portieren Ihrer WinINet-Anwendung

Erwägen Sie, Ihre WinINet-Anwendung zu WinHTTP zu portieren, wenn Ihre Anwendung von folgenden Vorteilen profitieren würde:

  • Ein serversicherer HTTP-Clientstapel.
  • Minimierte Stapelnutzung.
  • Die Skalierbarkeit einer Serveranwendung.
  • Weniger Abhängigkeiten von plattformbezogenen APIs.
  • Unterstützung für Threadidentitätswechsel.
  • Ein dienstfreundlicher HTTP-Stapel.
  • Zugriff auf das skriptfähige WinHttpRequest-Objekt .

Erwägen Sie nicht, Ihre WinINet-Anwendung nach WinHTTP zu portieren, wenn sie mindestens eine der folgenden Komponenten unterstützen muss:

  • Das FTP- oder Gopher-Protokoll aus dem HTTP-Stapel.
  • Unterstützung des SOCKSv4-Protokolls für die Kommunikation mit SOCKS-Proxys.
  • Automatische DFÜ-Dienste.

Wenn Sie sich entscheiden, Ihre Anwendung zu WinHTTP zu portieren, führen Sie die folgenden Abschnitte durch den Konvertierungsprozess.

Vergleichen Sie für eine Beispielanwendung für WinINet und WinHTTP das AsyncDemo-Beispiel für WinINet mit dem AsyncDemo-Beispiel für WinHTTP.

WinHTTP-Entsprechungen zu WinINet-Funktionen

In der folgenden Tabelle sind WinINet-Funktionen im Zusammenhang mit dem HTTP-Clientstapel zusammen mit den WinHTTP-Entsprechungen aufgeführt.

Wenn Ihre Anwendung WinINet-Funktionen erfordert, die nicht aufgeführt sind, portieren Sie Ihre Anwendung nicht nach WinHTTP.

WinINet-Funktion WinHTTP-Entsprechung Wichtige Änderungen
HttpAddRequestHeaders WinHttpAddRequestHeaders Keine
HttpEndRequest WinHttpReceiveResponse Der Kontextwert wird mit WinHttpSendRequest oder WinHttpSetOption festgelegt. Anforderungsoptionen werden mit WinHttpOpenRequest festgelegt. WinHttpReceiveResponse muss aufgerufen werden, nachdem eine Anforderung gesendet wurde.
HttpOpenRequest WinHttpOpenRequest Der Kontextwert wird mit WinHttpSendRequest oder WinHttpSetOption festgelegt.
HttpQueryInfo WinHttpQueryHeaders Keine
HttpSendRequest WinHttpSendRequest Der Kontextwert kann mit WinHttpSendRequest festgelegt werden.
HttpSendRequestEx WinHttpSendRequest Puffer können nicht bereitgestellt werden.
InternetCanonicalizeUrl Keine Entsprechung URLs werden jetzt in WinHttpOpenRequest in kanonischer Form platziert.
InternetCheckConnection Keine Entsprechung Nicht in WinHTTP implementiert.
InternetCloseHandle WinHttpCloseHandle Das Schließen eines übergeordneten Handles in WinHTTP schließt untergeordnete Handles nicht rekursiv.
InternetCombineUrl Keine Entsprechung URLs können mit der WinHttpCreateUrl-Funktion zusammengestellt werden.
InternetConfirmZoneCrossing Keine Entsprechung Nicht in WinHTTP implementiert.
InternetConnect WinHttpConnect Der Kontextwert wird mit WinHttpSendRequest oder WinHttpSetOption festgelegt. Anforderungsoptionen werden mit WinHttpOpenRequest festgelegt. Benutzeranmeldeinformationen werden mit WinHttpSetCredentials festgelegt.
InternetCrackUrl WinHttpCrackUrl Entgegengesetztes Verhalten des ICU_ESCAPE-Flags: Mit InternetCrackUrl bewirkt dieses Flag, dass Escapesequenzen (%xx) in Zeichen konvertiert werden, aber mit WinHttpCrackUrl werden Zeichen, die in einer HTTP-Anforderung mit Escapezeichen versehen werden müssen, in Escapesequenzen konvertiert.
InternetCreateUrl WinHttpCreateUrl Keine
InternetErrorDlg Keine Entsprechung Da WinHTTP auf serverseitige Anwendungen ausgerichtet ist, implementiert es keine Benutzeroberfläche.
InternetGetCookie Keine Entsprechung WinHTTP speichert keine Daten zwischen Sitzungen und kann nicht auf WinINet-Cookies zugreifen.
InternetOpen WinHttpOpen Keine
InternetOpenUrl WinHttpConnect, WinHttpOpenRequest, WinHttpSendRequest, WinHttpReceiveResponse Diese Funktionalität ist in den aufgeführten WinHTTP-Funktionen verfügbar.
InternetQueryDataAvailable WinHttpQueryDataAvailable Keine reservierten Parameter.
InternetQueryOption WinHttpQueryOption WinHTTP bietet einen anderen Satz von Optionen als WinINet. Weitere Informationen und Optionen, die von WinHTTP angeboten werden, finden Sie unter Optionsflags.
InternetReadFile WinHttpReadData Keine
InternetReadFileEx WinHttpReadData Anstelle einer Struktur ist der Puffer ein Bereich des Arbeitsspeichers, der mit einem Zeiger adressiert wird.
InternetSetOption WinHttpSetOption Keine
InternetSetStatusCallback WinHttpSetStatusCallback Weitere Informationen finden Sie unter "Unterschiedliche Behandlung von asynchronen Anforderungen" in diesem Thema.
InternetTimeFromSystemTime WinHttpTimeFromSystemTime Keine
InternetTimeToSystemTime WinHttpTimeToSystemTime Keine
InternetWriteFile WinHttpWriteData Keine

 

Unterschiedliche Behandlung von asynchronen Anforderungen

Beachten Sie, dass in WinINet und WinHTTP einige Funktionen asynchrone Anforderungen entweder synchron oder asynchron abschließen können. Ihre Anwendung muss beide Situationen verarbeiten. Es gibt erhebliche Unterschiede in der Handhabung dieser potenziell asynchronen Funktionen durch WinINet und WinHTTP.

Wininet

  • Synchrone Vervollständigung: Wenn ein potenziell asynchroner WinINet-Funktionsaufruf synchron abgeschlossen wird, geben die OUT-Parameter der Funktion die Ergebnisse des Vorgangs zurück. Wenn ein Fehler auftritt, rufen Sie den Fehlercode ab, indem Sie GetLastError nach dem WinINet-Funktionsaufruf aufrufen.

  • Asynchrone Vervollständigung: Wenn ein potenziell asynchroner Funktionsaufruf asynchron abgeschlossen wird, sind die Ergebnisse des Vorgangs und alle Fehler in der Rückruffunktion verfügbar. Die Rückruffunktion wird in einem Workerthread ausgeführt, nicht in dem Thread, der den ersten Funktionsaufruf ausgeführt hat.

Anders ausgedrückt: Ihre Anwendung muss logik duplizieren, um die Ergebnisse solcher Vorgänge an zwei Stellen zu verarbeiten: sowohl unmittelbar nach dem Funktionsaufruf als auch in der Rückruffunktion.

WinHTTP vereinfacht dieses Modell, indem Sie die Betriebslogik nur in der Rückruffunktion implementieren können, die unabhängig davon, ob der Vorgang synchron oder asynchron abgeschlossen wurde, eine Abschlussbenachrichtigung empfängt. Wenn der asynchrone Vorgang aktiviert ist, geben die OUT-Parameter der WinHTTP-Funktionen keine aussagekräftigen Daten zurück und müssen auf NULL festgelegt werden.

Der einzige signifikante Unterschied zwischen asynchroner und synchroner Vervollständigung in WinHTTP besteht aus Anwendungssicht darin, wo die Rückruffunktion ausgeführt wird.

WinHTTP

  • Synchrone Vervollständigung: Wenn ein Vorgang synchron abgeschlossen wird, werden die Ergebnisse in einer Rückruffunktion zurückgegeben, die im selben Thread wie der ursprüngliche Funktionsaufruf ausgeführt wird.

  • Asynchrone Vervollständigung: Wenn ein Vorgang asynchron abgeschlossen wird, werden die Ergebnisse in einer Rückruffunktion zurückgegeben, die in einem Workerthread ausgeführt wird.

Obwohl die meisten Fehler auch vollständig innerhalb der Rückruffunktion behandelt werden können, müssen WinHTTP-Anwendungen dennoch darauf vorbereitet sein, dass eine Funktion FALSE aufgrund eines ERROR_INVALID_PARAMETER oder eines ähnlichen Fehlers zurückgibt, der durch Aufrufen von GetLastError abgerufen wird.

Im Gegensatz zu WinINet, das mehrere asynchrone Vorgänge gleichzeitig ausführen kann, erzwingt WinHTTP eine Richtlinie eines ausstehenden asynchronen Vorgangs pro Anforderungshandle. Wenn ein Vorgang aussteht und eine andere WinHTTP-Funktion aufgerufen wird, schlägt die zweite Funktion fehl, und GetLastError gibt ERROR_INVALID_OPERATION zurück.

WinHTTP vereinfacht dieses Modell, indem Sie die Betriebslogik nur in der Rückruffunktion implementieren können, die unabhängig davon, ob der Vorgang synchron oder asynchron abgeschlossen wurde, eine Abschlussbenachrichtigung empfängt. Wenn der asynchrone Vorgang aktiviert ist, geben die OUT-Parameter der WinHTTP-Funktionen keine aussagekräftigen Daten zurück und müssen auf NULL festgelegt werden.

Unterschiede bei WinHTTP-Rückrufbenachrichtigungen

Die rückruffunktion status empfängt Updates über die status von Vorgängen über Benachrichtigungsflags. In WinHTTP werden Benachrichtigungen mithilfe des dwNotificationFlags-Parameters der WinHttpSetStatusCallback-Funktion ausgewählt. Verwenden Sie das flag WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, um über alle status Updates benachrichtigt zu werden.

Benachrichtigungen, die angeben, dass ein bestimmter Vorgang abgeschlossen ist, werden als Abschlussbenachrichtigungen oder einfach als Vervollständigungen bezeichnet. In WinINet enthält der lpvStatusInformation-Parameter jedes Mal, wenn die Rückruffunktion eine Vervollständigung empfängt, eine INTERNET_ASYNC_RESULT-Struktur . In WinHTTP ist diese Struktur nicht für alle Vervollständigungen verfügbar. Es ist wichtig, die Referenzseite für WINHTTP_STATUS_CALLBACK zu überprüfen, die Informationen zu Benachrichtigungen enthält und welche Art von Daten für die einzelnen Daten erwartet werden können.

In WinHTTP gibt ein einzelner Abschluss (WINHTTP_CALLBACK_STATUS_REQUEST_ERROR) an, dass ein Vorgang fehlgeschlagen ist. Alle anderen Vervollständigungen weisen auf einen erfolgreichen Vorgang hin.

Sowohl WinINet als auch WinHTTP verwenden einen benutzerdefinierten Kontextwert, um Informationen aus dem Standard Thread an die rückruffunktion status zu übergeben, die in einem Workerthread ausgeführt werden kann. In WinINet wird der von der status Rückruffunktion verwendete Kontextwert durch Aufrufen einer von mehreren Funktionen festgelegt. In WinHTTP wird der Kontextwert nur mit WinHttpSendRequest oder WinHttpSetOption festgelegt. Aus diesem Grund ist es in WinHTTP möglich, dass eine Benachrichtigung erfolgt, bevor ein Kontextwert festgelegt wird. Wenn die Rückruffunktion eine Benachrichtigung empfängt, bevor der Kontextwert festgelegt wird, muss die Anwendung darauf vorbereitet sein , NULL im dwContext-Parameter der Rückruffunktion zu empfangen.

Authentifizierungsunterschiede

In WinINet werden Die Benutzeranmeldeinformationen durch Aufrufen der InternetSetOption-Funktion mithilfe von Code festgelegt, der dem im folgenden Codebeispiel ähnelt.

// Use the WinINet InternetSetOption function to set the 
// user credentials to the user name contained in strUsername 
// and the password to the contents of strPassword.
       
InternetSetOption( hRequest, INTERNET_OPTION_PROXY_USERNAME, 
                   strUsername, strlen(strUsername) + 1 );

InternetSetOption( hRequest, INTERNET_OPTION_PROXY_PASSWORD, 
                   strPassword, strlen(strPassword) + 1 );

Aus Gründen der Kompatibilität können Benutzeranmeldeinformationen auch in WinHTTP mithilfe der WinHttpSetOption-Funktion festgelegt werden. Dies wird jedoch nicht empfohlen, da sie ein Sicherheitsrisiko darstellen kann.

Wenn eine Anwendung stattdessen einen 401-status-Code in WinHTTP empfängt, besteht die empfohlene Methode zum Festlegen von Anmeldeinformationen darin, zunächst ein Authentifizierungsschema mithilfe von WinHttpQueryAuthSchemes zu identifizieren und anschließend die Anmeldeinformationen mithilfe von WinHttpSetCredentials festzulegen. Im folgenden Codebeispiel wird dies veranschaulicht.

DWORD dwSupportedSchemes;
DWORD dwPrefered;
DWORD dwTarget;

// Obtain the supported and first schemes.
WinHttpQueryAuthSchemes( hRequest, &dwSupportedSchemes, &dwPrefered, &dwTarget );

// Set the credentials before resending the request.
WinHttpSetCredentials( hRequest, dwTarget, dwPrefered, strUsername, strPassword, NULL );

Da es in WinHTTP keine Entsprechung zu InternetErrorDlg gibt, müssen Anwendungen, die Anmeldeinformationen über eine Benutzeroberfläche abrufen, eine eigene Schnittstelle bereitstellen.

Im Gegensatz zu WinINet speichert WinHTTP keine Kennwörter zwischen. Für jede Anforderung müssen gültige Benutzeranmeldeinformationen angegeben werden.

WinHTTP unterstützt das von WinINet unterstützte DPA-Schema (Distributed Password Authentication). WinHTTP unterstützt jedoch Microsoft Passport 1.4. Weitere Informationen zur Verwendung der Passport-Authentifizierung in WinHTTP finden Sie unter Passport-Authentifizierung in WinHTTP.

WinHTTP verwendet keine Internet-Explorer Einstellungen, um die Richtlinie für die automatische Anmeldung zu bestimmen. Stattdessen wird die Richtlinie für die automatische Anmeldung mit WinHttpSetOption festgelegt. Weitere Informationen zur Authentifizierung in WinHTTP, einschließlich der Richtlinie für die automatische Anmeldung, finden Sie unter Authentifizierung in WinHTTP.

Unterschiede bei sicheren HTTP-Transaktionen

Initiieren Sie in WinINet eine sichere Sitzung entweder mit HttpOpenRequest oder InternetConnect, aber in WinHTTP müssen Sie WinHttpOpenRequest mit dem WINHTTP_FLAG_SECURE-Flag aufrufen.

In einer sicheren HTTP-Transaktion können Serverzertifikate verwendet werden, um einen Server beim Client zu authentifizieren. Wenn in WinINet ein Serverzertifikat Fehler enthält, schlägt HttpSendRequest fehl und stellt Details zu den Zertifikatfehlern bereit.

In WinHttp werden Serverzertifikatfehler gemäß der Version wie folgt behandelt:

  • Ab WinHttp 5.1 meldet der Aufruf von WinHttpSendRequest einen WINHTTP_CALLBACK_STATUS_SECURE_FAILURE in der Rückruffunktion, wenn ein Serverzertifikat ausfällt oder Fehler enthält. Wenn der von WinHttpSendRequest generierte Fehler ignoriert wird, schlagen nachfolgende Aufrufe von WinHttpReceiveResponse mit einem ERROR_WINHTTP_OPERATION_CANCELLED Fehler fehl.
  • In WinHTTP 5.0 führen Fehler in Serverzertifikaten standardmäßig nicht dazu, dass eine Anforderung fehlschlägt. Stattdessen werden die Fehler in der Rückruffunktion mit der WINHTTP_CALLBACK_STATUS_SECURE_FAILURE Benachrichtigung gemeldet.

Auf einigen früheren Plattformen unterstützte WinINet die Protokolle Private Communication Technology (PCT) und/oder Fortezza, jedoch nicht unter Windows XP.

WinHTTP unterstützt die Protokolle PCT und Fortezza auf keiner Plattform und basiert stattdessen auf Secure Sockets Layer (SSL) 2.0, SSL 3.0 oder TLS 1.0 (Transport Layer Security).