用 HTTP 协议下载资源(WinINet 实现)
用 HTTP 协议下载资源(WinINet 实现)
WinINet 使用 HTTP 协议下载资源的流程
相关函数
InternetCrackUrl
解析 URL
BOOL InternetCrackUrl(
_In_ LPCTSTR lpszUrl, // (1)
_In_ DWORD dwUrlLength, // (2)
_In_ DWORD dwFlags, // (3)
_Inout_ LPURL_COMPONENTS lpUrlComponents // (4)
);
(1) Pointer to a string that contains the canonical URL to be cracked.
(2) Size of the lpszUrl string, in TCHAR
s, or zero if lpszUrl is an ASCIIZ string
(3) Controls the operation: ICU_DECODE
(Converts encoded characters back to their normal form), ICU_ESCAPE
(Converts all escape sequences (%xx) to their corresponding characters)
(4) Pointer to a URL_COMPONENTS
structure that receives the URL components.
InternetOpen
初始化应用程序对 WinINet 的使用
InternetOpen
是应用程序调用的第一个 WinINet 函数。 它用来告诉 Internet DLL 初始化内部数据结构, 为未来应用程序的调用做准备。当应用程序不再使用 Internet 函数时, 需要调用InternetCloseHandle
来释放句柄及其关联的资源。
HINTERNET InternetOpen(
_In_ LPCTSTR lpszAgent, // (1)
_In_ DWORD dwAccessType, // (2)
_In_ LPCTSTR lpszProxyName, // (3)
_In_ LPCTSTR lpszProxyBypass, // (4)
_In_ DWORD dwFlags // (5)
);
(1) Pointer to a null-terminated string that specifies the name of the application or entity calling the WinINet functions. This name is used as the user agent in the HTTP protocol.
(2) Type of access required:
INTERNET_OPEN_TYPE_DIRECT
: Resolves all host names locally;INTERNET_OPEN_TYPE_PRECONFIG
: Retrieves the proxy or direct configuration from the registry;INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY
: Retrieves the proxy or direct configuration from the registry and prevents the use of a startup Microsoft JScript or Internet Setup (INS) file;INTERNET_OPEN_TYPE_PROXY
: Passes requests to the proxy unless a proxy bypass list is supplied and the name to be resolved bypasses the proxy. In this case, the function usesINTERNET_OPEN_TYPE_DIRECT
(3) Pointer to a null-terminated string that specifies the name of the proxy server(s) to use when proxy access is specified by setting dwAccessType to INTERNET_OPEN_TYPE_PROXY
.
(4) Pointer to a null-terminated string that specifies an optional list of host names or IP addresses, or both, that should not be routed through the proxy when dwAccessType is set to INTERNET_OPEN_TYPE_PROXY
.
(5) Options:
INTERNET_FLAG_ASYNC
: Makes only asynchronous requests on handles descended from the handle returned from this function;INTERNET_FLAG_FROM_CACHE
: Does not make network requests. All entities are returned from the cache);INTERNET_FLAG_OFFLINE
: Identical toINTERNET_FLAG_FROM_CACHE
InternetConnect
为指定网站打开一个文件传输协议(File Transfer Protocol, FTP) 或 HTTP 协议 的会话(session)
HINTERNET InternetConnect(
_In_ HINTERNET hInternet, // (1)
_In_ LPCTSTR lpszServerName, // (2)
_In_ INTERNET_PORT nServerPort, // (3)
_In_ LPCTSTR lpszUsername, // (4)
_In_ LPCTSTR lpszPassword, // (5)
_In_ DWORD dwService, // (6)
_In_ DWORD dwFlags, // (7)
_In_ DWORD_PTR dwContext // (8)
);
(1) Handle returned by a previous call to InternetOpen
.
(2) Pointer to a null-terminated string that specifies the host name of an Internet server. Alternately, the string can contain the IP number of the site, in ASCII dotted-decimal format (for example, 11.0.1.45).
(3) Transmission Control Protocol/Internet Protocol (TCP/IP) port on the server.
(4) Pointer to a null-terminated string that specifies the name of the user to log on. If this parameter is NULL, the function uses an appropriate default.
(5) Pointer to a null-terminated string that contains the password to use to log on. If both lpszPassword and lpszUsername are NULL, the function uses the default “anonymous” password.
(6) Type of service to access:
INTERNET_SERVICE_FTP
: FTP service;INTERNET_SERVICE_GOPHER
: Gopher service;INTERNET_SERVICE_HTTP
: HTTP service
(7) Options specific to the service used.
(8) Pointer to a variable that contains an application-defined value that is used to identify the application context for the returned handle in callbacks.
HttpOpenRequest
创建 HTTP 请求(request) 句柄
如果指定了除 “GET” 或 “POST” 以外的请求方法动词,
HttpOpenRequest
自动为请求设置INTERNET_FLAG_NO_CACHE_WRITE
和INTERNET_FLAG_RELOAD
.
HINTERNET HttpOpenRequest(
_In_ HINTERNET hConnect, // (1)
_In_ LPCTSTR lpszVerb, // (2)
_In_ LPCTSTR lpszObjectName, // (3)
_In_ LPCTSTR lpszVersion, // (4)
_In_ LPCTSTR lpszReferer, // (5)
_In_ LPCTSTR *lplpszAcceptTypes, // (6)
_In_ DWORD dwFlags, // (7)
_In_ DWORD_PTR dwContext // (8)
);
(1) A handle to an HTTP session returned by InternetConnect
.
(2) A pointer to a null-terminated string that contains the HTTP verb to use in the request. If this parameter is NULL
, the function uses GET as the HTTP verb.
(3) A pointer to a null-terminated string that contains the name of the target object of the specified HTTP verb. This is generally a file name, an executable module, or a search specifier. (即, 请求资源的 URI)
(4) A pointer to a null-terminated string that contains the HTTP version to use in the request.If this parameter is NULL, the function uses an HTTP version of 1.1 or 1.0, depending on the value of the Internet Explorer settings.(一般设置为 “HTTP/1.0” 或 “HTTP/1.1”)
(5) A pointer to a null-terminated string that specifies the URL of the document from which the URL in the request (lpszObjectName
) was obtained. If this parameter is NULL, no referrer is specified.
(6) A pointer to a null-terminated array of strings that indicates media types accepted by the client.Here is an example.
PCTSTR rgpszAcceptTypes[] = {_T(“text/*”), NULL};
(7) Internet options: INTERNET_FLAG_RELOAD
(Forces a download of the requested file, object, or directory listing from the origin server, not from the cache), INTERNET_FLAG_NO_CACHE_WRITE
(Does not add the returned entity to the cache) 等。
(8) A pointer to a variable that contains the application-defined value that associates this operation with any application data.
HttpAddRequestHeaders
向 HTTP 的请求句柄添加首部字段
BOOL HttpAddRequestHeaders(
_In_ HINTERNET hRequest, // (1)
_In_ LPCTSTR lpszHeaders, // (2)
_In_ DWORD dwHeadersLength, // (3)
_In_ DWORD dwModifiers // (4)
);
(1) A handle returned by a call to the HttpOpenRequest function.
(2) A pointer to a string variable containing the headers to append to the request. Each header must be terminated by a CR/LF (carriage return/line feed) pair.
(3) The size of lpszHeaders
, in TCHARs. If this parameter is -1L, the function assumes that lpszHeaders
is zero-terminated (ASCIIZ), and the length is computed.
(4) A set of modifiers that control the semantics of this function:
HTTP_ADDREQ_FLAG_ADD
: Adds the header if it does not exist. Used withHTTP_ADDREQ_FLAG_REPLACE
;HTTP_ADDREQ_FLAG_ADD_IF_NEW
: Adds the header only if it does not already exist; otherwise, an error is returned;HTTP_ADDREQ_FLAG_COALESCE
: Coalesces(使联合;使合并) headers of the same nameHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA
: Coalesces headers of the same name with comma(逗号). For example, adding “Accept: text/” followed by “Accept: audio/” with this flag results in the formation of the single header “Accept: text/, audio/“;HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON
: Coalesces headers of the same name using a semicolon(分号);HTTP_ADDREQ_FLAG_REPLACE
: Replaces or removes a header. If the header value is empty and the header is found, it is removed. If not empty, the header value is replaced.
HttpSendRequest
发送 Http 请求
BOOL HttpSendRequest(
_In_ HINTERNET hRequest, (1)
_In_ LPCTSTR lpszHeaders, (2)
_In_ DWORD dwHeadersLength, (3)
_In_ LPVOID lpOptional, (4)
_In_ DWORD dwOptionalLength (5)
);
(1) A handle returned by a call to the HttpOpenRequest
function.
(2) A pointer to a null-terminated string that contains the additional headers to be appended to the request. This parameter can be NULL if there are no additional headers to be appended.
(3) The size of the additional headers, in TCHARs. If this parameter is -1L
and lpszHeaders is not NULL
, the function assumes that lpszHeaders is zero-terminated (ASCIIZ), and the length is calculated.
(4) A pointer to a buffer containing any optional data to be sent immediately after the request headers. This parameter is generally used for “POST” and “PUT” operations.
(5) The size of the optional data, in bytes.
HttpQueryInfo
获取 HTTP 请求的响应情况
BOOL HttpQueryInfo(
_In_ HINTERNET hRequest, // (1)
_In_ DWORD dwInfoLevel, // (2)
_Inout_ LPVOID lpvBuffer, // (3)
_Inout_ LPDWORD lpdwBufferLength, // (4)
_Inout_ LPDWORD lpdwIndex // (5)
);
(1) A handle returned by a call to the HttpOpenRequest
or InternetOpenUrl
function.
(2) A combination of an attribute to be retrieved and flags that modify the request. For a list of possible attribute and modifier values, see Query Info Flags.
HTTP_QUERY_CONTENT_LENGTH
(Retrieves the size of the resource, in bytes),HTTP_QUERY_ACCEPT_RANGES
(Retrieves the types of range requests that are accepted for a resource),HTTP_QUERY_CONTENT_RANGE
(HTTP_QUERY_CONTENT_RANGE),HTTP_QUERY_FLAG_NUMBER
(Returns the data as a 32-bit number for headers whose value is a number, such as the status code),HTTP_QUERY_STATUS_CODE
(Receives the status code returned by the server) 等
(3) A pointer to a buffer to receive the requested information.
(4) A pointer to a variable that contains, on entry, the size in bytes of the buffer pointed to by lpvBuffer
. When the function returns successfully, this variable contains the number of bytes of information written to the buffer. In the case of a string, the byte count does not include the string’s terminating null character.
(5) A pointer to a zero-based header index used to enumerate multiple headers with the same name.
InternetReadFile
从 InternetOpenUrl
, FtpOpenFile
, 或 HttpOpenRequest
打开的句柄中读取数据。
为了保证所有的数据都被读取, 需要循环调用 InternetReadFile
函数, 直到返回的 lpdwNumberOfBytesRead
参数为 0。
BOOL InternetReadFile(
_In_ HINTERNET hFile, // (1)
_Out_ LPVOID lpBuffer, // (2)
_In_ DWORD dwNumberOfBytesToRead, // (3)
_Out_ LPDWORD lpdwNumberOfBytesRead // (4)
);
(1) Handle returned from a previous call to InternetOpenUrl
, FtpOpenFile
, or HttpOpenRequest
.
(2) Pointer to a buffer that receives the data.
(3) Number of bytes to be read.
(4) Pointer to a variable that receives the number of bytes read. InternetReadFile
sets this value to zero before doing any work or error checking.
样例代码
#include <string>
#include <iostream>
#include <windows.h>
#include <WinINet.h>
using namespace std;
#pragma comment(lib, "WinINet.lib")
int main(int argc, char* argv[])
{
wstring strURL = L"http://blog.csdn.net/yanglingwell/article/details/78258081";
// 解析 URL
URL_COMPONENTS urlComponents;
ZeroMemory(&urlComponents, sizeof(urlComponents));
WCHAR lpszHostName[INTERNET_MAX_HOST_NAME_LENGTH] = {0};
WCHAR lpszUserName[INTERNET_MAX_USER_NAME_LENGTH] = {0};
WCHAR lpszPassword[INTERNET_MAX_PASSWORD_LENGTH] = {0};
WCHAR lpszURLPath[INTERNET_MAX_URL_LENGTH] = {0};
WCHAR lpszScheme[INTERNET_MAX_SCHEME_LENGTH] = {0};
urlComponents.dwStructSize = sizeof(URL_COMPONENTSA);
urlComponents.lpszScheme = lpszScheme;
urlComponents.dwSchemeLength = INTERNET_MAX_SCHEME_LENGTH;
urlComponents.lpszHostName = lpszHostName;
urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
urlComponents.lpszUserName = lpszUserName;
urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH;
urlComponents.lpszPassword = lpszPassword;
urlComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH;
urlComponents.lpszUrlPath = lpszURLPath;
urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
BOOL bSuccess = InternetCrackUrl(strURL.data(), 0, NULL, &urlComponents);
if(bSuccess == FALSE)
{
wcout << strURL << L" 解析失败!" << endl;
return 0;
}
else if(urlComponents.nScheme != INTERNET_SCHEME_HTTP)
{
wcout << strURL << L" 不是 HTTP 协议!" << endl;
return 0;
}
HINTERNET hSession = NULL;
HINTERNET hInternet = NULL;
HINTERNET hRequest = NULL;
do
{
// Initializes an application's use of the WinINet functions.
// Returns a valid handle that the application passes to subsequent WinINet functions.
// If InternetOpen fails, it returns NULL.
hInternet = InternetOpen(L"yanglingwell", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(hInternet == NULL)
{
cout << "InternetOpen failed. errCode: " << GetLastError() << endl;
break;
}
// Opens an HTTP session for a given site.
// Returns a valid handle to the session if the connection is successful, or NULL otherwise.
HINTERNET hSession = InternetConnect(hInternet, urlComponents.lpszHostName, urlComponents.nPort, urlComponents.lpszUserName,
urlComponents.lpszPassword, INTERNET_SERVICE_HTTP, 0, NULL);
if(hSession == NULL)
{
cout << "InternetConnect failed. errCode: " << GetLastError() << endl;
break;
}
// Creates an HTTP request handle
// Returns an HTTP request handle if successful, or NULL otherwise.
hRequest = HttpOpenRequest(hSession, L"GET", urlComponents.lpszUrlPath, NULL, L"", NULL, 0, 0);
if(hRequest == NULL)
{
cout << "HttpOpenRequest failed. errCode: " << GetLastError() << endl;
break;
}
// 设置首部字段
wstring strHeader;
// 设置接受数据类型
strHeader += L"Accept: */*\r\n";
// 设置禁止用缓存和缓存控制
strHeader += L"Pragma: no-cache\r\n";
strHeader += L"Cache-Control: no-cache\r\n";
// 设置其它首部字段....
// Adds one or more HTTP request headers to the HTTP request handle.
if (!HttpAddRequestHeaders(hRequest, strHeader.data(), strHeader.length(), HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE))
{
cout << "HttpAddRequestHeaders failed. errCode: " << GetLastError() << endl;
break;
}
if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0))
{
cout << "HttpAddRequestHeaders failed. errCode: " << GetLastError() << endl;
break;
}
DWORD dwStatusCode;
DWORD dwSizeDW = sizeof(DWORD);
if (!HttpQueryInfo(hRequest, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE, &dwStatusCode, &dwSizeDW, NULL))
{
cout << "HttpQueryInfo failed. errCode: " << GetLastError() << endl;
break;
}
else
{
cout << "StatusCode: " << dwStatusCode << endl;
}
WCHAR buf[2048];
DWORD bufSize = sizeof(buf);
DWORD bufRead = 0;
do
{
if(!InternetReadFile(hRequest, &buf, bufSize, &bufRead))
{
cout << "InternetReadFile failed. errCode: " << GetLastError() << endl;
break;
}
wcout << L"reading..." << endl;
} while (bufRead != 0);
} while (FALSE);
if(hInternet != NULL)
{
InternetCloseHandle(hInternet);
}
if(hSession != NULL)
{
InternetCloseHandle(hSession);
}
if(hRequest != NULL)
{
InternetCloseHandle(hRequest);
}
return 0;
}
用 HTTP 协议下载资源(WinINet 实现)的更多相关文章
- WinInet API详解
一.概述 WinInet(「Windows Internet」)API帮助程序员使用三个常见的Internet协议,这三个协议是:用于World Wide Web万维网的超文本传输协议(HTTP:Hy ...
- loadrunner11录制报 NOT PROXIED!错误,无法生成脚本
使用loadrunner11,IE9录制完脚本,报错: [Net An. Error (1dec:282c)] Request Connection: Remote Server @ 210.5 ...
- LoadRunner中 host-mapping的Capture Level说明
lr录制后空白,那么就要弄明白lr中host-mapping的Capture Level选项socket level data.winnet level data.socket level andwi ...
- Aria2+百度网盘 无限制的下载神器
Aria2是一款免费开源跨平台且不限速的多线程下载软件,Aria2的优点是速度快.体积小.资源占用少:支持 HTTP / FTP / BT / Magnet 磁力链接等类型的文件下载:支持 Win.M ...
- 力推:无限制下载神器aria2
百度网盘是一个非常方便的存储以及寻找资源的好帮手,但是百度为了挣钱把非会员的下载网速一再限制(无力吐槽),还还好一直使用油猴插件加idm下载神器来下载百度云文件.奈何idm对bt种子文件不支持下载,终 ...
- LoadRunner的Capture Level说明
LoadRunner的Capture Level说明 Capture Level的设置说明: 1.Socket level data. Capture data using trapping on t ...
- loadrunner录制时web时,ie报安全证书问题
解决方法:在Recording_Options下Port Mapping>Capture level设置为 WinNet level data Capture Level的设置说明:1.Sock ...
- 使用Fiddler对android应用抓http或https包
工作原理 先上个图 此图一目了然,可以看出fiddler在请求中所处的位置,我们就可以确定它能干些什么. WinInet(“Windows Internet”)API帮助程序员使用三个常见的Int ...
- 使用Fiddler对android应用抓包 专题
工作原理 先上个图 此图一目了然,可以看出fiddler在请求中所处的位置,我们就可以确定它能干些什么. WinInet(“Windows Internet”)API帮助程序员使用三个常见的Inter ...
- Windows 配置 Aria2 及 Web 管理面板教程
今天闲来没事,想找点东西折腾下,然后看到个在 Debian 7 x64 系统环境下配置 Aria2 和 Web 管理面板的教程,针对 Linux 服务器用的.但很多人没服务器,也不知道什么是 Aria ...
随机推荐
- python进阶(29)单例模式
初识单例模式 单例模式含义 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对象的类必须保证只有一个实例存在.许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整 ...
- 解决can't compare offset-naive and offset-aware datetimes报错
问题描述 在比较 <class 'datetime.datetime'> 类型时,抛出异常 原因 俩个做比较的,一个具有时区,一个不具有时区 解决 如果可以确认俩个时间都是本地时间可以将时 ...
- 关于windows7打不开hlp文件的解决方法
前言 其实也不是打不开,而是打开后是这样的. 也就是相当于打不开. 解决方案 安装对应架构版本补丁,重启电脑即可. 下载地址 包含64位和32位. 有能力的还望下载这个 下载地址 给我留点积分,感谢!
- Java开发学习(四十六)----MyBatisPlus新增语句之id生成策略控制及其简化配置
在前面有一篇博客:Java开发学习(四十一)----MyBatisPlus标准数据层(增删查改分页)开发,我们在新增的时候留了一个问题,就是新增成功后,主键ID是一个很长串的内容. 我们更想要的是按照 ...
- sql周报
数据库分类 1.关系型数据库 Mysql Qracle MariaDB PostgreSQL mysql:开源免费 使用最广 性价比最高 Oracle:收费 但安全性高 PostgreSQL:开源免费 ...
- sha1_b64_scrape
过无限debugger:https://www.cnblogs.com/hkwJsxl/p/16702143.html 网站 aHR0cHM6Ly9hbnRpc3BpZGVyOC5zY3JhcGUuY ...
- 【Spring专题】「开发指南」夯实实战基础功底之解读logback-spring.xml文件的详解实现
logback的maven配置 <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j- ...
- 从Babel开始认识AST抽象语法树
前言 AST抽象语法树想必大家都有听过这个概念,但是不是只停留在听过这个层面呢.其实它对于编程来讲是一个非常重要的概念,当然也包括前端,在很多地方都能看见AST抽象语法树的影子,其中不乏有vue.re ...
- OPPO 后端开发 一、二面面经
你好,我是 Guide,看了这么多面试成功的经验分享,今天来看一个读者分享的 Oppo 秋招面试失败经历. 面经合集请看:Java面试题&面经精选集. 下面是正文(文中的我为读者本人). 个人 ...
- 真正“搞”懂HTTP协议07之队头阻塞真的很烦人
这一篇文章,我们核心要聊的事情就是HTTP的对头阻塞问题,因为HTTP的核心改进其实就是在解决HTTP的队头阻塞.所以,我们会讲的理论多一些,而实践其实很少,要学习的头字段也只有一个,我会在最开始就讲 ...