65.9K
CodeProject 正在变化。 阅读更多。
Home

功能齐全的 Windows HTTP 包装器(C++)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (97投票s)

2010年3月19日

CPOL

3分钟阅读

viewsIcon

483807

downloadIcon

22586

一个功能齐全且易于使用的 C++ Windows HTTP 包装器。

引言

这是一个全功能的 Windows HTTP 封装器,使用 C++ 开发。它是一个 C++ 类的封装器,功能齐全且易于使用。您只需要包含一个头文件即可使用该封装器。

背景

几个月前,我在 CodeProject 上发表了第一篇文章 一个简单的 Windows HTTP 封装器,使用 C++ 开发。在过去的几个月里,我不断更新它,最终得到了基于 C++ 中 WinHTTP API 的全功能 Windows HTTP 封装器。

特点

  • 支持 Cookie
  • 支持代理
  • 支持 GETPOST 方法
  • 支持自定义请求头
  • 支持禁用自动重定向
  • 支持 HTTPS
  • 支持接收进度
  • 其他一些特性

Using the Code

类图如下:

class.JPG

您可以从函数名称中理解大多数函数的功能。请参考示例部分了解一些典型示例。

示例

简单的 Get 请求

Get 请求是最常见的请求。浏览网页会导致一个或多个 Get 请求。

// Set URL.
WinHttpClient client(L"https://codeproject.org.cn/");
 
// Send HTTP request, a GET request by default.
client.SendHttpRequest();
 
// The response header.
wstring httpResponseHeader = client.GetResponseHeader();
 
// The response content.
wstring httpResponseContent = client.GetResponseContent();

简单的 Post 请求

Post 请求通常发生在登录或发布帖子时。

WinHttpClient client(L"https://codeproject.org.cn/");
 
// Set post data.
string data = "title=A_NEW_THREAD&content=This_is_a_new_thread.";
client.SetAdditionalDataToSend((BYTE *)data.c_str(), data.size());
 
// Set request headers.
wchar_t szSize[50] = L"";
swprintf_s(szSize, L"%d", data.size());
wstring headers = L"Content-Length: ";
headers += szSize;
headers += L"\r\nContent-Type: application/x-www-form-urlencoded\r\n";
client.SetAdditionalRequestHeaders(headers);
 
// Send HTTP post request.
client.SendHttpRequest(L"POST");
 
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();

获取请求的进度

您可以指定一个回调函数来获取请求的进度。

// Progress - finished percentage.
bool ProgressProc(double progress)
{
    wprintf(L"Current progress: %-.1f%%\r\n", progress);
    return true;
}
 
void ProgressTest(void)
{
    // Set URL and call back function.
    WinHttpClient client(L"https://codeproject.org.cn/", ProgressProc);
    client.SendHttpRequest();
    wstring httpResponseHeader = client.GetResponseHeader();
    wstring httpResponseContent = client.GetResponseContent();
}

指定用户代理

用户代理是一个 string,客户端使用它来向 Web 服务器标识自己,以便服务器可以知道您使用的客户端软件,例如 Internet Explorer 8、Chrome 或 FireFox。您可以指定用户代理来伪装成 Internet Explorer 8,从而欺骗 Web 服务器,因为有时服务器仅支持 Internet Explorer 8。

WinHttpClient client(L"https://codeproject.org.cn/");
 
// Set the user agent to the same as Internet Explorer 8.
client.SetUserAgent(L"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1;...)");
 
client.SendHttpRequest();
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();

指定代理

有时,我们必须通过代理连接到 Web。默认情况下,WinHttpClient 直接连接到 Web 服务器,如果连接失败,则使用 Internet Explorer 设置进行连接。您也可以通过调用函数 SetProxy 来指定代理。

WinHttpClient client(L"https://codeproject.org.cn/");
 
// Set the proxy to 192.168.0.1 with port 8080.
client.SetProxy(L"192.168.0.1:8080");
 
client.SendHttpRequest();
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();

处理 Cookies

Cookie(也称为跟踪 Cookie、浏览器 Cookie 和 HTTP Cookie)是由 Web 浏览器存储在用户计算机上的一个小文本片段。Cookie 由包含信息位的一个或多个名称-值对组成。

Cookie 由 Web 服务器作为 HTTP 标头发送到 Web 浏览器,然后每次浏览器访问该服务器时,都会将 Cookie 不变地发送回服务器。Cookie 可用于身份验证、会话跟踪(状态维护)、存储站点首选项、购物车内容、基于服务器的会话的标识符,或可以通过存储文本数据实现的任何其他操作 (http://en.wikipedia.org/wiki/HTTP_cookie)。

您可以通过调用 SetAdditionalRequestCookies 来指定要发送的 Cookie,并通过调用 GetResponseCookies 来获取响应 Cookie。

WinHttpClient client(L"https://codeproject.org.cn/");
 
// Set the cookies to send.
client.SetAdditionalRequestCookies(L"username=jack");
 
client.SendHttpRequest();
 
// Get the response cookies.
wstring httpResponseCookies = client.GetResponseCookies();
 
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();

HTTPS

WinHttpClient client(L"https://www.google.com/");

// Accept any certificate while performing HTTPS request.
client.RequireValidSslCertificates(false);

client.SendHttpRequest();
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();

多个请求

WinHttpClient client(L"http://www.google.com/");
 
client.SendHttpRequest();
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();

// Update the URL.
client.UpdateUrl(L"http://www.microsoft.com/");
client.SendHttpRequest();
httpResponseHeader = client.GetResponseHeader();
httpResponseContent = client.GetResponseContent();

一个完整的示例

Codeproject.com 需要登录才能下载文件。此示例登录,获取 Cookie,请求我的第一篇 CodeProject 文章 一个简单的 Windows HTTP 封装器,使用 C++ 开发 的源代码 (win_HTTP_wrapper/WinHttpClient_Src.zip),然后将文件保存到硬盘。此示例包括 Cookie 处理、Post 请求、请求头自定义等。

// 1. Get the initial cookie.
WinHttpClient getClient
	(L"https://codeproject.org.cn/script/Membership/LogOn.aspx");
getClient.SetAdditionalRequestHeaders
	(L"Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, ...");
if (!getClient.SendHttpRequest())
{
    return;
}
 
// 2. Post data to get the authentication cookie.
WinHttpClient postClient
	(L"https://codeproject.org.cn/script/Membership/LogOn.aspx?rp=
	%2fscript%2fMembership%2fLogOn.aspx");
 
// Post data.
wstring username = L"YourCodeProjectUsername";
wstring password = L"YourPassword";
postClient.SetAdditionalRequestCookies(getClient.GetResponseCookies());
string data = "FormName=MenuBarForm&Email=";
data += (char *)_bstr_t(username.c_str());
data += "&Password=";
data += (char *)_bstr_t(password.c_str());
data += "&RememberMeCheck=1";
postClient.SetAdditionalDataToSend((BYTE *)data.c_str(), data.size());
 
// Post headers.
wstring headers = L"...Content-Length: %d\r\nProxy-Connection: 
		Keep-Alive\r\nPragma: no-cache\r\n";
wchar_t szHeaders[MAX_PATH * 10] = L"";
swprintf_s(szHeaders, MAX_PATH * 10, headers.c_str(), data.size());
postClient.SetAdditionalRequestHeaders(szHeaders);
if (!postClient.SendHttpRequest(L"POST", true))
{
    return;
}
 
// 3. Finally get the zip file.    
WinHttpClient downloadClient(L"win_HTTP_wrapper/WinHttpClient_Src.zip");
downloadClient.SetUserAgent(L"Mozilla/4.0 
		(compatible; MSIE 8.0; Windows NT 5.1; ...)");
 
// Sending this cookie makes the server believe you have already logged in.
downloadClient.SetAdditionalRequestCookies(postClient.GetResponseCookies());
if (!downloadClient.SendHttpRequest())
{
    return;
}
downloadClient.SaveResponseToFile(L"C:\\WinHttpClient_Src.zip");

关注点

  • 有时,先让一段新代码运行起来,然后再改进它,是个好主意。
  • 阅读超文本传输协议 (RFC 2616) 将有很大帮助。
  • 使用 HTTP 监控工具来帮助开发,例如 HTTPAnalyzerHTTPWatch
  • 使用类 _bstr_twchar_t*char* 之间进行转换非常快速且容易。

历史

  • 2010-9-21 2 项增强功能,感谢 Scott Leckie
  • 2010-4-29 修复了 2 个错误,感谢 Wong Shao Voon
  • 2009-9 全功能版本
  • 2008-7 初始版本
© . All rights reserved.