Allgemeine Funktionen (Windows Internet)
Die verschiedenen Internetprotokolle (z. B. ftp und http) verwenden mehrere der gleichen WinINet-Funktionen, um Informationen im Internet zu verarbeiten. Diese allgemeinen Funktionen behandeln ihre Aufgaben einheitlich, unabhängig vom jeweiligen Protokoll, auf das sie angewendet werden. Anwendungen können diese Funktionen verwenden, um allgemeine Funktionen zu erstellen, die Aufgaben in den verschiedenen Protokollen verarbeiten (z. B. Lesen von Dateien für FTP und HTTP).
Die allgemeinen Funktionen behandeln die folgenden Aufgaben:
- Herunterladen von Ressourcen aus dem Internet (InternetReadFile, InternetSetFilePointer, InternetFindNextFileund InternetQueryDataAvailable).
- Einrichten asynchroner Vorgänge (InternetSetStatusCallback).
- Anzeigen und Ändern von Optionen (InternetSetOption und InternetQueryOption).
- Schließen aller Arten von HINTERNET Handles (InternetCloseHandle).
- Platzieren und Entfernen von Sperren für Ressourcen (InternetLockRequestFile und InternetUnlockRequestFile).
Verwenden allgemeiner Funktionen
In der folgenden Tabelle sind die allgemeinen Funktionen aufgeführt, die in den WinINet-Funktionen enthalten sind. Die allgemeinen Funktionen können auf verschiedenen Arten von HINTERNET- Handles verwendet werden oder während unterschiedlicher Sitzungstypen verwendet werden.
Funktion | Beschreibung |
---|---|
InternetFindNextFile- | Setzt die Dateiaufzählung oder Suche fort. Erfordert ein Handle, das vom FtpFindFirstFile-oder InternetOpenUrl--Funktion erstellt wird. |
InternetLockRequestFile- | Ermöglicht dem Benutzer, eine Sperre für die verwendete Datei zu platzieren. Diese Funktion erfordert ein Handle, das von der FtpOpenFile-, HttpOpenRequest-oder InternetOpenUrl--Funktion zurückgegeben wird. |
InternetQueryDataAvailable- | Ruft die verfügbare Datenmenge ab. Erfordert ein Handle, das vom FtpOpenFile-oder HttpOpenRequest--Funktion erstellt wird. |
InternetQueryOption- | Ruft die Einstellung einer Internetoption ab. |
InternetReadFile- | Liest URL-Daten. Erfordert ein Handle, das vom InternetOpenUrl-, FtpOpenFile-oder HttpOpenRequest--Funktion erstellt wird. |
InternetSetFilePointer- | Legt die Position für den nächsten Lesevorgang in einer Datei fest. Erfordert ein Handle, das von InternetOpenUrl- (nur auf einer HTTP-URL) oder einem Handle erstellt wurde, das von HttpOpenRequest mithilfe des GET-HTTP-Verbs erstellt wurde. |
InternetSetOption- | Legt eine Internetoption fest. |
InternetSetStatusCallback- | Legt eine Rückruffunktion fest, die Statusinformationen empfängt. Weist der angegebenen HINTERNET- Handle und allen von ihr abgeleiteten Handles eine Rückruffunktion zu. |
InternetUnlockRequestFile- | Entsperrt eine Datei, die mithilfe der InternetLockRequestFile--Funktion gesperrt wurde. |
Das Lesen von Dateien, das Auffinden der nächsten Datei, das Bearbeiten von Optionen und das Einrichten asynchroner Vorgänge gelten häufig für die Funktionen, die verschiedene Protokolle unterstützen, und HINTERNET- Behandeln von Typen.
Lesen von Dateien
Die InternetReadFile--Funktion wird verwendet, um Ressourcen aus einem HINTERNET- Handle herunterzuladen, das von der InternetOpenUrl-, FtpOpenFile-oder HttpOpenRequest-Funktion zurückgegeben wird.
InternetReadFile- akzeptiert eine leere Zeigervariable, die die Adresse eines Puffers und einen Zeiger auf eine Variable enthält, die die Länge des Puffers enthält. Die Funktion gibt die Daten im Puffer und die Datenmenge zurück, die in den Puffer heruntergeladen wurde.
Die WinINet-Funktionen bieten zwei Techniken zum Herunterladen einer gesamten Ressource:
- Die funktion InternetQueryDataAvailable.
- Die Rückgabewerte von InternetReadFile-.
InternetQueryDataAvailable übernimmt das HINTERNET- Handle, das von InternetOpenUrl, FtpOpenFile-oder HttpOpenRequest- erstellt wurde (nachdem HttpSendRequest aufgerufen wurde) und gibt die Anzahl der verfügbaren Bytes zurück. Die Anwendung sollte einen Puffer zuweisen, der der anzahl der verfügbaren Bytes entspricht, plus 1 für das Beenden Null- Zeichen, und diesen Puffer mit InternetReadFile-verwenden. Diese Methode funktioniert nicht immer, da InternetQueryDataAvailable- die in der Kopfzeile aufgeführte Dateigröße und nicht die tatsächliche Datei überprüft. Die Informationen in der Headerdatei könnten veraltet sein, oder die Headerdatei fehlt, da sie derzeit nicht unter allen Standards erforderlich ist.
Im folgenden Beispiel wird der Inhalt der Ressource gelesen, auf die vom hResource-Handle zugegriffen wird und im bearbeitungsfeld angezeigt wird, das durch intCtrlID angegeben ist.
int WINAPI Dumper(HWND hX, int intCtrlID, HINTERNET hResource)
{
LPTSTR lpszData; // buffer for the data
DWORD dwSize; // size of the data available
DWORD dwDownloaded; // size of the downloaded data
DWORD dwSizeSum=0; // size of the data in the text box
LPTSTR lpszHolding; // buffer to merge the text box
// data and buffer
// Set the cursor to an hourglass.
SetCursor(LoadCursor(NULL,IDC_WAIT));
// This loop handles reading the data.
do
{
// The call to InternetQueryDataAvailable determines the
// amount of data available to download.
if (!InternetQueryDataAvailable(hResource,&dwSize,0,0))
{
ErrorOut(hX,GetLastError(),TEXT("InternetReadFile"));
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
else
{
// Allocate a buffer of the size returned by
// InternetQueryDataAvailable.
lpszData = new TCHAR[dwSize+1];
// Read the data from the HINTERNET handle.
if(!InternetReadFile(hResource,(LPVOID)lpszData,
dwSize,&dwDownloaded))
{
ErrorOut(hX,GetLastError(),TEXT("InternetReadFile"));
delete[] lpszData;
break;
}
else
{
// Add a null terminator to the end of the
// data buffer.
lpszData[dwDownloaded]='\0';
// Allocate the holding buffer.
lpszHolding = new TCHAR[dwSizeSum + dwDownloaded + 1];
// Check if there has been any data written to
// the text box.
if (dwSizeSum != 0)
{
// Retrieve the data stored in the text
// box, if any.
GetDlgItemText(hX,intCtrlID,
(LPTSTR)lpszHolding,
dwSizeSum);
// Add a null terminator at the end of
// the text box data.
lpszHolding[dwSizeSum]='\0';
}
else
{
// Make the holding buffer an empty string.
lpszHolding[0]='\0';
}
size_t cchDest = dwSizeSum + dwDownloaded +
dwDownloaded + 1;
LPTSTR pszDestEnd;
size_t cchRemaining;
// Add the new data to the holding buffer.
HRESULT hr = StringCchCatEx(lpszHolding, cchDest,
lpszData, &pszDestEnd,
&cchRemaining,
STRSAFE_NO_TRUNCATION);
if(SUCCEEDED(hr))
{
// Write the holding buffer to the text box.
SetDlgItemText(hX,intCtrlID,(LPTSTR)lpszHolding);
// Delete the two buffers.
delete[] lpszHolding;
delete[] lpszData;
// Add the size of the downloaded data to
// the text box data size.
dwSizeSum = dwSizeSum + dwDownloaded + 1;
// Check the size of the remaining data.
// If it is zero, break.
if (dwDownloaded == 0)
{
break;
}
else
{
// Insert error handling code here.
}
}
}
}
}
while(TRUE);
// Close the HINTERNET handle.
InternetCloseHandle(hResource);
// Set the cursor back to an arrow.
SetCursor(LoadCursor(NULL,IDC_ARROW));
// Return.
return TRUE;
}
InternetReadFile- gibt null Bytes gelesen und erfolgreich abgeschlossen, wenn alle verfügbaren Daten gelesen wurden. Dadurch kann eine Anwendung InternetReadFile- in einer Schleife verwenden, um die Daten herunterzuladen und zu beenden, wenn null Bytes gelesen und erfolgreich abgeschlossen werden.
Im folgenden Beispiel wird die Ressource aus dem Internet gelesen und die Ressource im Bearbeitungsfeld angezeigt, das durch intCtrlID angegeben ist. Das HINTERNET handle, hInternet, wurde von InternetOpenUrl, FtpOpenFileoder HttpOpenRequest (nach dem Senden von HttpSendRequest) zurückgegeben.
int WINAPI Dump(HWND hX, int intCtrlID, HINTERNET hResource)
{
DWORD dwSize = 0;
LPTSTR lpszData;
LPTSTR lpszOutPut;
LPTSTR lpszHolding = TEXT("");
int nCounter = 1;
int nBufferSize = 0;
DWORD BigSize = 8000;
// Set the cursor to an hourglass.
SetCursor(LoadCursor(NULL,IDC_WAIT));
// Begin the loop that reads the data.
do
{
// Allocate the buffer.
lpszData =new TCHAR[BigSize+1];
// Read the data.
if(!InternetReadFile(hResource,
(LPVOID)lpszData,
BigSize,&dwSize))
{
ErrorOut(hX,GetLastError(),TEXT("InternetReadFile"));
delete []lpszData;
break;
}
else
{
// Add a null terminator to the end of the buffer.
lpszData[dwSize]='\0';
// Check if all of the data has been read. This should
// never get called on the first time through the loop.
if (dwSize == 0)
{
// Write the final data to the text box.
SetDlgItemText(hX,intCtrlID,lpszHolding);
// Delete the existing buffers.
delete [] lpszData;
delete [] lpszHolding;
break;
}
// Determine the buffer size to hold the new data and
// the data already written to the text box (if any).
nBufferSize = (nCounter*BigSize)+1;
// Increment the number of buffers read.
nCounter++;
// Allocate the output buffer.
lpszOutPut = new TCHAR[nBufferSize];
// Make sure the buffer is not the initial buffer.
if(nBufferSize != int(BigSize+1))
{
// Copy the data in the holding buffer.
StringCchCopy(lpszOutPut,nBufferSize,lpszHolding);
// Add error handling code here.
// Concatenate the new buffer with the
// output buffer.
StringCchCat(lpszOutPut, nBufferSize, lpszData);
// Add error handling code here.
// Delete the holding buffer.
delete [] lpszHolding;
}
else
{
// Copy the data buffer.
StringCchCopy(lpszOutPut, nBufferSize, lpszData);
// Add error handling code here.
}
// Allocate a holding buffer.
lpszHolding = new TCHAR[nBufferSize];
// Copy the output buffer into the holding buffer.
memcpy(lpszHolding,lpszOutPut,nBufferSize);
// Delete the other buffers.
delete [] lpszData;
delete [] lpszOutPut;
}
}
while (TRUE);
// Close the HINTERNET handle.
InternetCloseHandle(hResource);
// Set the cursor back to an arrow.
SetCursor(LoadCursor(NULL,IDC_ARROW));
// Return.
return TRUE;
}
Suchen der nächsten Datei
Die funktion InternetFindNextFile wird verwendet, um die nächste Datei in einer Dateisuche mithilfe der Suchparameter und HINTERNET Handle von FtpFindFirstFileoder InternetOpenUrlzu finden.
Um eine Dateisuche abzuschließen, rufen Sie weiterhin InternetFindNextFile- mithilfe des HINTERNET Handle auf, das von FtpFindFirstFilezurückgegeben wird, oder InternetOpenUrl, bis die Funktion mit der erweiterten Fehlermeldung fehlschlägt ERROR_NO_MORE_FILES. Rufen Sie zum Abrufen der erweiterten Fehlerinformationen die GetLastError--Funktion auf.
Im folgenden Beispiel wird der Inhalt eines FTP-Verzeichnisses im durch lstDirectory angegebenen Listenfeld angezeigt. Das HINTERNET Handle hConnect ist ein Handle, das von der InternetConnect-Funktion zurückgegeben wird, nachdem eine FTP-Sitzung eingerichtet wurde.
bool WINAPI DisplayDir( HWND hX,
int lstDirectory,
HINTERNET hConnect,
DWORD dwFlag )
{
WIN32_FIND_DATA pDirInfo;
HINTERNET hDir;
TCHAR DirList[MAX_PATH];
// Set the cursor to an hourglass.
SetCursor(LoadCursor(NULL,IDC_WAIT));
// Reset the list box.
SendDlgItemMessage(hX, lstDirectory,LB_RESETCONTENT,0,0);
// Find the first file.
hDir = FtpFindFirstFile (hConnect, TEXT ("*.*"),
&pDirInfo, dwFlag, 0);
if (!hDir)
{
// Check if the error was because there were no files.
if (GetLastError() == ERROR_NO_MORE_FILES)
{
// Alert user.
MessageBox(hX, TEXT("There are no files here!!!"),
TEXT("Display Dir"), MB_OK);
// Close the HINTERNET handle.
InternetCloseHandle(hDir);
// Set the cursor back to an arrow.
SetCursor(LoadCursor(NULL,IDC_ARROW));
// Return.
return TRUE;
}
else
{
// Call error handler.
ErrorOut (hX, GetLastError (), TEXT("FindFirst error: "));
// Close the HINTERNET handle.
InternetCloseHandle(hDir);
// Set the cursor back to an arrow.
SetCursor(LoadCursor(NULL,IDC_ARROW));
// Return.
return FALSE;
}
}
else
{
// Write the file name to a string.
StringCchPrintf(DirList, MAX_PATH, pDirInfo.cFileName);
// Check the type of file.
if (pDirInfo.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
{
// Add <DIR> to indicate that this is
// a directory to the user.
StringCchCat(DirList, MAX_PATH, TEXT(" <DIR> "));
// Add error handling code here.
}
// Add the file name (or directory) to the list box.
SendDlgItemMessage(hX, lstDirectory, LB_ADDSTRING,
0, (LPARAM)DirList);
}
do
{
// Find the next file.
if (!InternetFindNextFile (hDir, &pDirInfo))
{
// Check if there are no more files left.
if ( GetLastError() == ERROR_NO_MORE_FILES )
{
// Close the HINTERNET handle.
InternetCloseHandle(hDir);
// Set the cursor back to an arrow.
SetCursor(LoadCursor(NULL,IDC_ARROW));
// Return.
return TRUE;
}
else
{
// Handle the error.
ErrorOut (hX, GetLastError(),
TEXT("InternetFindNextFile"));
// Close the HINTERNET handle.
InternetCloseHandle(hDir);
// Set the cursor back to an arrow.
SetCursor(LoadCursor(NULL,IDC_ARROW));
// Return.
return FALSE;
}
}
else
{
// Write the file name to a string.
StringCchPrintf(DirList, MAX_PATH, pDirInfo.cFileName);
// Check the type of file.
if(pDirInfo.dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY)
{
// Add <DIR> to indicate that this is a
// directory to the user.
StringCchCat(DirList, MAX_PATH, TEXT(" <DIR> "));
// Add error handling code here.
}
// Add the file name (or directory) to the list box.
SendDlgItemMessage(hX, lstDirectory, LB_ADDSTRING,
0, (LPARAM)DirList);
}
}
while ( TRUE);
}
Bearbeiten von Optionen
InternetSetOption und InternetQueryOption werden verwendet, um die WinINet-Optionen zu bearbeiten.
InternetSetOption akzeptiert eine Variable, die die festzulegende Option angibt, einen Puffer, der die Optionseinstellung enthält, und einen Zeiger, der die Adresse der Variablen enthält, die die Länge des Puffers enthält.
InternetQueryOption akzeptiert eine Variable, die die Abzurufende Option angibt, einen Puffer, der die Optionseinstellung enthält, und einen Zeiger, der die Adresse der Variablen enthält, die die Länge des Puffers enthält.
Einrichten asynchroner Vorgänge
Standardmäßig werden die WinINet-Funktionen synchron ausgeführt. Eine Anwendung kann einen asynchronen Vorgang anfordern, indem das INTERNET_FLAG_ASYNC Flag im Aufruf der InternetOpen--Funktion festgelegt wird. Alle zukünftigen Aufrufe für Von InternetOpen zurückgegebene Handle werden asynchron ausgeführt.
Der Grund für asynchronen und synchronen Betrieb besteht darin, einer Singlethread-Anwendung die Maximierung der Auslastung der CPU zu ermöglichen, ohne auf den Abschluss der Netzwerk-E/A warten zu müssen. Je nach Anforderung kann der Vorgang daher synchron oder asynchron abgeschlossen werden. Die Anwendung sollte den Rückgabecode überprüfen. Wenn eine Funktion FALSE- oder NULL-zurückgibt und GetLastError ERROR_IO_PENDING zurückgibt, wurde die Anforderung asynchron ausgeführt, und die Anwendung wird mit INTERNET_STATUS_REQUEST_COMPLETE zurückgerufen, wenn die Funktion abgeschlossen wurde.
Um einen asynchronen Vorgang zu starten, muss die Anwendung das INTERNET_FLAG_ASYNC Flag im Aufruf von InternetOpenfestlegen. Die Anwendung muss dann eine gültige Rückruffunktion mit InternetSetStatusCallback-registrieren.
Nachdem eine Rückruffunktion für ein Handle registriert wurde, können alle Vorgänge auf diesem Handle Statusanzeigen generieren, sofern der Kontextwert, der beim Erstellen des Handles angegeben wurde, nicht null war. Das Bereitstellen eines Nullkontextwerts erzwingt die synchrone Ausführung eines Vorgangs, obwohl INTERNET_FLAG_ASYNC in InternetOpenangegeben wurde.
Statusanzeigen geben der Anwendung Feedback zum Fortschritt von Netzwerkvorgängen, z. B. das Auflösen eines Hostnamens, das Herstellen einer Verbindung mit einem Server und das Empfangen von Daten. Für einen Handle können drei Spezielle Statusanzeigen vorgenommen werden:
- INTERNET_STATUS_HANDLE_CLOSING ist die letzte Statusanzeige, die für einen Handle erstellt wird.
- INTERNET_STATUS_HANDLE_CREATED gibt an, wann das Handle anfangs erstellt wird.
- INTERNET_STATUS_REQUEST_COMPLETE gibt an, dass ein asynchroner Vorgang abgeschlossen wurde.
Die Anwendung muss die INTERNET_ASYNC_RESULT Struktur überprüfen, um festzustellen, ob der Vorgang erfolgreich war oder fehlgeschlagen ist, nachdem eine INTERNET_STATUS_REQUEST_COMPLETE Indikation empfangen wurde.
Das folgende Beispiel zeigt ein Beispiel für eine Rückruffunktion und einen Aufruf von InternetSetStatusCallback-, um die Funktion als Rückruffunktion zu registrieren.
void CALLBACK InternetCallback(
HINTERNET hInternet,
DWORD_PTR dwcontext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength
)
{
_tprintf(TEXT("%0xd %0xp %0xd %0xp %0xd\n"),
hInternet,
dwcontext,
dwInternetStatus,
lpvStatusInformation,
dwStatusInformationLength);
};
INTERNET_STATUS_CALLBACK dwISC =
InternetSetStatusCallback(hInternet, InternetCallback);
Schließen von HINTERNET-Handles
Alle HINTERNET- Handles können mithilfe der InternetCloseHandle--Funktion geschlossen werden. Clientanwendungen müssen alle HINTERNET- Handles schließen, die vom HINTERNET- Handle abgeleitet sind, das sie schließen möchten, bevor sie InternetCloseHandle- für das Handle aufrufen.
Das folgende Beispiel veranschaulicht die Handlehierarchie.
HINTERNET hRootHandle, hOpenUrlHandle;
hRootHandle = InternetOpen( TEXT("Example"),
INTERNET_OPEN_TYPE_DIRECT,
NULL,
NULL, 0);
hOpenUrlHandle = InternetOpenUrl(hRootHandle,
TEXT("https://www.server.com/default.htm"), NULL, 0,
INTERNET_FLAG_RAW_DATA,0);
// Close the handle created by InternetOpenUrl so that the
// InternetOpen handle can be closed.
InternetCloseHandle(hOpenUrlHandle);
// Close the handle created by InternetOpen.
InternetCloseHandle(hRootHandle);
Sperren und Entsperren von Ressourcen
Mit der InternetLockRequestFile--Funktion kann eine Anwendung sicherstellen, dass die mit dem HINTERNET- übergebene Handle nicht aus dem Cache verschwindet. Wenn ein anderer Download versucht, eine Ressource mit derselben URL wie die gesperrte Datei zu übernehmen, verhindert der Cache das Entfernen der Datei durch sicheres Löschen. Nachdem die Anwendung die InternetUnlockRequestFile--Funktion aufgerufen hat, erhält der Cache die Berechtigung zum Löschen der Datei.
Wenn das flag INTERNET_FLAG_NO_CACHE_WRITE oder INTERNET_FLAG_DONT_CACHE festgelegt wurde, erstellt InternetLockRequestFile eine temporäre Datei mit der Erweiterung TMP, es sei denn, das Handle ist mit einer https-Ressource verbunden. Wenn die Funktion auf eine HTTPS-Ressource zugreift und INTERNET_FLAG_NO_CACHE_WRITE (oder INTERNET_FLAG_DONT_CACHE) festgelegt wurde, schlägt InternetLockRequestFile- fehl.
Anmerkung
WinINet unterstützt keine Serverimplementierungen. Darüber hinaus sollte sie nicht von einem Dienst verwendet werden. Verwenden Sie für Serverimplementierungen oder -dienste Microsoft Windows HTTP Services (WinHTTP).