Microsoft Windows HTTP服务(WinHTTP)公开了一组C / C ++函数,使您的应用程序能够访问Web上的HTTP资源。 本主题概述了如何使用这些函数与HTTP服务器交互。
下图显示了与HTTP服务器交互时通常调用WinHTTP函数的顺序。 阴影框表示生成HINTERNET句柄的函数,而平面框表示使用这些句柄的函数。
在与服务器交互之前,WinHTTP
必须通过调用WinHttpOpen
进行初始化。 WinHttpOpen
创建会话上下文以维护有关HTTP
会话的详细信息,并返回会话句柄。使用此句柄,WinHttpConnect
功能然后能够指定目标HTTP
或安全超文本传输协议(HTTPS
)服务器。
注意: 对特定资源发出请求之前,对WinHttpConnect
的调用不会导致与HTTP
服务器的实际连接。
WinHttpOpenRequest
函数打开特定资源的HTTP
请求,并返回一个可以被其他HTTP
函数使用的HINTERNET
句柄。 WinHttpOpenRequest
在调用时不会将请求发送到服务器。 WinHttpSendRequest
函数实际上通过网络建立连接并发送请求。
以下示例显示了使用默认选项调用WinHttpOpenRequest
的示例。
HINTERNET hRequest = WinHttpOpenRequest(hConnect,L“GET”,NULL,NULL,NULL,NULL,0);
WinHttpAddRequestHeaders
函数允许应用程序将附加的自由格式请求头附加到HTTP
请求句柄。它适用于需要精确控制发送到HTTP
服务器的请求的复杂应用程序。
WinHttpAddRequestHeaders
函数需要一个由WinHttpOpenRequest
创建的HTTP
请求句柄,该字符串包含头部,头部的长度和任何修饰符。
以下修饰符可以与WinHttpAddRequestHeaders
一起使用。
Modifier | Description |
---|---|
WINHTTP_ADDREQ_FLAG_ADD |
添加标题(如果它不存在)。与WINHTTP_ADDREQ_FLAG_REPLACE 一起使用。 |
WINHTTP_ADDREQ_FLAG_ADD_IF_NEW |
只有当头不存在时才添加头;否则返回错误。 |
WINHTTP_ADDREQ_FLAG_COALESCE |
合并同名的标题。 |
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA |
使用逗号合并同名的标题。例如,用此标志添加“Accept:text / ”后跟“Accept:audio / ”形成单个标题“Accept:text / ,audio / ”,导致找到的第一个标题合并。它取决于调用应用程序以确保关于合并/单独头部的粘性方案。 |
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON |
使用分号合并同名的标题。 |
WINHTTP_ADDREQ_FLAG_REPLACE |
替换或删除标头。如果标头值为空,并且找到标头,则将其删除。如果标头值不为空,则替换标头值。 |
WinHttpSendRequest
函数建立与服务器的连接,并将请求发送到指定的站点。此函数需要一个由WinHttpOpenRequest
创建的HINTERNET
句柄。 WinHttpSendRequest
也可以发送附加头或可选信息。可选信息通常用于向服务器写入信息的操作,例如PUT
和POST
。
在WinHttpSendRequest
函数发送请求后,应用程序可以使用HINTERNET
句柄上的WinHttpReadData
和WinHttpQueryDataAvailable
函数下载服务器的资源。
要将数据发布到服务器,调用WinHttpOpenRequest
中的HTTP
动词必须是POST
或PUT
。当调用WinHttpSendRequest
时,dwTotalLength
参数应设置为以字节为单位的数据大小。然后使用WinHttpWriteData
将数据发布到服务器。
或者,将WinHttpSendRequest
的lpOptional
参数设置为包含要发布到服务器的数据的缓冲区的地址。使用此技术时,必须将WinHttpSendRequest
的dwOptionalLength
和dwTotalLength
参数设置为要发布的数据的大小。以这种方式调用WinHttpSendRequest
消除了调用WinHttpWriteData
的需要。
WinHttpQueryHeaders
函数允许应用程序检索有关HTTP
请求的信息。该函数需要由WinHttpOpenRequest
创建的HINTERNET
句柄,信息级别值和缓冲区长度。 WinHttpQueryHeaders
也接受一个存储信息的缓冲区和一个基于零的头索引,枚举多个同名的头。
使用在查询信息标志页面上找到的任何信息级别值以及一个修饰符来控制信息存储在WinHttpQueryHeaders
的lpvBuffer
参数中的格式。
在使用WinHttpOpenRequest
函数打开请求后,使用WinHttpSendRequest
将其发送到服务器,并准备请求句柄以接收具有WinHttpReceiveResponse
的响应,应用程序可以使用WinHttpReadData
和WinHttpQueryDataAvailable
函数从HTTP
服务器下载资源。
以下示例代码显示如何使用安全事务语义下载资源。示例代码初始化WinHTTP
应用程序编程接口(API),选择目标HTTPS
服务器,然后打开并发送此安全资源的请求。 WinHttpQueryDataAvailable
与请求句柄一起使用,以确定有多少数据可供下载,然后WinHttpReadData
用于读取该数据。重复该过程,直到整个文档被检索和显示。
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
BOOL bResults = FALSE;
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen( L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0 );
// Specify an HTTP server.
if( hSession )
hConnect = WinHttpConnect( hSession, L"www.microsoft.com",
INTERNET_DEFAULT_HTTPS_PORT, 0 );
// Create an HTTP request handle.
if( hConnect )
hRequest = WinHttpOpenRequest( hConnect, L"GET", NULL,
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE );
// Send a request.
if( hRequest )
bResults = WinHttpSendRequest( hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
WINHTTP_NO_REQUEST_DATA, 0,
0, 0 );
// End the request.
if( bResults )
bResults = WinHttpReceiveResponse( hRequest, NULL );
// Keep checking for data until there is nothing left.
if( bResults )
{
do
{
// Check for available data.
dwSize = 0;
if( !WinHttpQueryDataAvailable( hRequest, &dwSize ) )
printf( "Error %u in WinHttpQueryDataAvailable.\n",
GetLastError( ) );
// Allocate space for the buffer.
pszOutBuffer = new char[dwSize+1];
if( !pszOutBuffer )
{
printf( "Out of memory\n" );
dwSize=0;
}
else
{
// Read the data.
ZeroMemory( pszOutBuffer, dwSize+1 );
if( !WinHttpReadData( hRequest, (LPVOID)pszOutBuffer,
dwSize, &dwDownloaded ) )
printf( "Error %u in WinHttpReadData.\n", GetLastError( ) );
else
printf( "%s", pszOutBuffer );
// Free the memory allocated to the buffer.
delete [] pszOutBuffer;
}
} while( dwSize > 0 );
}
// Report any errors.
if( !bResults )
printf( "Error %d has occurred.\n", GetLastError( ) );
// Close any open handles.
if( hRequest ) WinHttpCloseHandle( hRequest );
if( hConnect ) WinHttpCloseHandle( hConnect );
if( hSession ) WinHttpCloseHandle( hSession );