HTTP 会话
WinINet 使你能够访问万维网 (WWW) 上的资源。 可以使用 InternetOpenUrl (直接访问这些资源,有关详细信息,请参阅 直接访问 url) 。
WWW 上的资源是使用 http 访问的。 HTTP 函数处理基础协议,同时允许应用程序访问 WWW 上的信息。 随着 HTTP 协议的发展,基础协议将更新以维护函数行为。
下图显示了与 HTTP 协议一起使用的函数的关系。 带阴影的框表示返回 HINTERNET 句柄的函数,而普通框表示使用由它们所依赖的函数创建的 HINTERNET 句柄的函数。
有关详细信息,请参阅 HINTERNET 句柄。
使用 WinINet 函数访问 WWW
在 HTTP 会话期间使用以下函数来访问 WWW。
函数 | 说明 |
---|---|
HttpAddRequestHeaders | 将 HTTP 请求标头添加到 HTTP 请求句柄。 此函数需要 HttpOpenRequest 创建的句柄。 |
HttpOpenRequest | 打开 HTTP 请求句柄。 此函数需要 InternetConnect 创建的句柄。 |
HttpQueryInfo | 查询有关 HTTP 请求的信息。 此函数需要 HttpOpenRequest 或 InternetOpenUrl 函数创建的句柄。 |
HttpSendRequest | 将指定的 HTTP 请求发送到 HTTP 服务器。 此函数需要 HttpOpenRequest 创建的句柄。 |
InternetErrorDlg | 显示常见 Internet 错误情况的预定义对话框。 此函数需要调用 HttpSendRequest 时使用的句柄。 |
启动与 WWW 的连接
若要开始与 WWW 的连接,应用程序必须在 InternetOpen 返回的根 HINTERNET 上调用 InternetConnect 函数。 InternetConnect 必须通过声明INTERNET_SERVICE_HTTP服务类型来建立 HTTP 会话。 有关使用 InternetConnect 的详细信息,请参阅 使用 InternetConnect。
打开请求
HttpOpenRequest 函数会打开 HTTP 请求并返回可供其他 HTTP 函数使用的 HINTERNET 句柄。 与其他开放函数 ((如 FtpOpenFile 和 InternetOpenUrl) )不同, HttpOpenRequest 在调用时不会将请求发送到 Internet。 HttpSendRequest 函数发送请求并通过网络建立连接。
HttpOpenRequest 采用 InternetConnect 创建的 HTTP 会话句柄和 HTTP 谓词、对象名称、版本字符串、引用者、接受类型、标志和上下文值。
HTTP 谓词是请求中使用的字符串。 请求中使用的常见 HTTP 谓词包括 GET、PUT 和 POST。 如果此值设置为 NULL, HttpOpenRequest 将使用默认值 GET。
对象名称是一个字符串,其中包含指定 HTTP 谓词的目标对象的名称。 这通常是文件名、可执行模块或搜索说明符。 如果提供的对象名称是空字符串, 则 HttpOpenRequest 将查找默认页面。
版本字符串应包含 HTTP 版本。 如果此参数为 NULL,则函数使用“HTTP/1.1”。
引用者指定从中获取对象名称的文档的地址。 如果此参数为 NULL,则不指定任何引用网站。
包含 accept 类型的 null 终止字符串指示应用程序接受的内容类型。 将此参数设置为 NULL 表示应用程序不接受任何内容类型。 如果提供了空字符串,则应用程序指示它只接受类型为“”text/*“的文档。 值“text/*”表示仅文本文档,而不是图片或其他二进制文件。
标志值控制缓存、Cookie 和安全问题。 对于 Microsoft 网络 (MSN) 、NTLM 和其他类型的身份验证,请设置 INTERNET_FLAG_KEEP_CONNECTION 标志。
如果在对 InternetOpen 的调用中设置了INTERNET_FLAG_ASYNC标志,则应设置非零上下文值以执行正确的异步操作。
以下示例是对 HttpOpenRequest 的示例调用。
hHttpRequest = HttpOpenRequest( hHttpSession, "GET", "", NULL, "", NULL, 0, 0);
添加请求标头
使用 HttpAddRequestHeaders 函数,应用程序可以将一个或多个请求标头添加到初始请求。 此函数允许应用程序将其他自由格式标头追加到 HTTP 请求句柄;它适用于需要精确控制发送到 HTTP 服务器的请求的复杂应用程序。
HttpAddRequestHeaders 需要 HttpOpenRequest 创建的 HTTP 请求句柄,该字符串包含标头、标头的长度和修饰符。
发送请求
HttpSendRequest 建立与 Internet 的连接,并将请求发送到指定的站点。 此函数需要 HttpOpenRequest 创建的 HINTERNET 句柄。 HttpSendRequest 还可以发送其他标头或可选信息。 可选信息通常用于将信息写入服务器的操作,例如 PUT 和 POST。
HttpSendRequest 发送请求后,应用程序可以使用 HttpOpenRequest 创建的 HINTERNET 句柄上的 InternetReadFile、InternetQueryDataAvailable 和 InternetSetFilePointer 函数来下载服务器的资源。
将数据发布到服务器
若要将数据发布到服务器,调用 HttpOpenRequest 中的 HTTP 谓词必须是 POST 或 PUT。 然后,包含 POST 数据的缓冲区的地址应传递到 HttpSendRequest 中的 lpOptional 参数。 dwOptionalLength 参数应设置为数据的大小。
还可以使用 InternetWriteFile 函数将数据发布到使用 HttpSendRequestEx 发送的 HINTERNET 句柄上。
获取有关请求的信息
HttpQueryInfo 允许应用程序检索有关 HTTP 请求的信息。 该函数需要 HttpOpenRequest 或 InternetOpenUrl 创建的 HINTERNET 句柄、信息级别值和缓冲区长度。 HttpQueryInfo 还接受一个存储信息的缓冲区和一个从零开始的标头索引,该索引枚举多个具有相同名称的标头。
从 WWW 下载资源
使用 HttpOpenRequest 打开请求并使用 HttpSendRequest 将其发送到服务器后,应用程序可以使用 InternetReadFile、 InternetQueryDataAvailable 和 InternetSetFilePointer 函数从 HTTP 服务器下载资源。
以下示例下载资源。 函数接受当前窗口的句柄、编辑框的标识号以及由 HttpOpenRequest 创建并由 HttpSendRequest 发送的 HINTERNET 句柄。 它使用 InternetQueryDataAvailable 来确定资源的大小,然后使用 InternetReadFile 下载资源。 然后,内容将显示在编辑框中。
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 textbox
LPTSTR lpszHolding; // buffer to merge the textbox 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))
{
printf("InternetQueryDataAvailable failed (%d)\n", GetLastError());
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))
{
printf("InternetReadFile failed (%d)\n", GetLastError());
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 textbox.
if (dwSizeSum != 0)
{
// Retrieve the data stored in the textbox if any
GetDlgItemText(hX,intCtrlID,
(LPTSTR)lpszHolding,
dwSizeSum);
// Add a null terminator at the end of the
// textbox data.
lpszHolding[dwSizeSum]='\0';
}
else
{
// Make the holding buffer an empty string.
lpszHolding[0]='\0';
}
size_t cchDest = dwSizeSum + dwDownloaded + dwDownloaded + 1;
LPTSTR* ppszDestEnd = 0;
size_t* pcchRemaining = 0;
// Add the new data to the holding buffer
HRESULT hr = StringCchCatEx(lpszHolding,
cchDest,
lpszData,
ppszDestEnd,
pcchRemaining,
STRSAFE_NO_TRUNCATION);
if(SUCCEEDED(hr))
{
// Write the holding buffer to the textbox.
SetDlgItemText(hX,intCtrlID,(LPTSTR)lpszHolding);
// Delete the two buffers.
delete[] lpszHolding;
delete[] lpszData;
// Add the size of the downloaded data to the
// textbox data size.
dwSizeSum = dwSizeSum + dwDownloaded + 1;
// Check the size of the remaining data.
// If it is zero, break.
if (dwDownloaded == 0)
break;
else
{
// TODO: 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 TRUE;
}
注意
WinINet 不支持服务器实现。 此外,不应从服务使用它。 对于服务器实现或服务,请使用 Microsoft Windows HTTP Services (WinHTTP) 。