# 基于WinInet实现的HTTP文件下载
# 背景
之前写过的网络数据传输的小程序都是基于Socket去写的,所以,如果要用Socket传输数据到网站,还需要根据域名获取服务器的IP地址,然后再建立连接,传输数据。虽然,Socket也可以实现网络传输,但是,总感觉不是很方便。所以,后来随着知识面的拓展,了解到Windows还专门提供了WinInet网络库,封装了比较简便的接口,去实现HTTP和FTP等传输协议的数据传输。
本文就是基于WinInet网络库,实现通过HTTP传输协议下载文件功能的小程序。现在,就把开发过程的思路和编程分享给大家。
# 主要函数介绍
介绍HTTP下载文件使用到的主要的WinInet库中的API函数。
## 1. InternetOpen介绍
> 函数声明
>
> ```c++
> HINTERNET InternetOpen(
> In LPCTSTR lpszAgent,
> In DWORD dwAccessType,
> In LPCTSTR lpszProxyName,
> In LPCTSTR lpszProxyBypass,
> In DWORD dwFlags
> );
> ```
>
> 参数
> lpszAgent
> 指向一个空结束的字符串,该字符串指定调用WinInet函数的应用程序或实体的名称。使用此名称作为用户代理的HTTP协议。
> dwAccessType
> 指定访问类型,参数可以是下列值之一:
>
> | Value | Meaning |
> | ---------------------------------------- | ---------------------------------------- |
> | INTERNET_OPEN_TYPE_DIRECT | 使用直接连接网络 |
> | INTERNET_OPEN_TYPE_PRECONFIG | 获取代理或直接从注册表中的配置,使用代理连接网络 |
> | INTERNET_OPEN_TYPE_PRECONFIG_ WITH_NO_AUTOPROXY | 获取代理或直接从注册表中的配置,并防止启动Microsoft JScript或Internet设置(INS)文件的使用 |
> | INTERNET_OPEN_TYPE_PROXY | 通过代理的请求,除非代理旁路列表中提供的名称解析绕过代理,在这种情况下,该功能的使用 |
>
>
> lpszProxyName
> 指针指向一个空结束的字符串,该字符串指定的代理服务器的名称,不要使用空字符串;如果dwAccessType未设置为INTERNET_OPEN_TYPE_PROXY,则此参数应该设置为NULL。
>
>
> lpszProxyBypass
> 指向一个空结束的字符串,该字符串指定的可选列表的主机名或IP地址。如果dwAccessType未设置为INTERNET_OPEN_TYPE_PROXY的 ,参数省略则为NULL。
>
>
> dwFlags
> 参数可以是下列值的组合:
>
> | VALUE | MEANING |
> | ------------------------ | ---------------------------------------- |
> | INTERNET_FLAG_ASYNC | 使异步请求处理的后裔从这个函数返回的句柄 |
> | INTERNET_FLAG_FROM_CACHE | 不进行网络请求,从缓存返回的所有实体,如果请求的项目不在缓存中,则返回一个合适的错误,如ERROR_FILE_NOT_FOUND |
> | INTERNET_FLAG_OFFLINE | 不进行网络请求,从缓存返回的所有实体,如果请求的项目不在缓存中,则返回一个合适的错误,如ERROR_FILE_NOT_FOUND |
>
>
> 返回值
> 成功:返回一个有效的句柄,该句柄将由应用程序传递给接下来的WinInet函数。
> 失败:返回NULL。
## 2. InternetConnect介绍
> 函数声明
>
> ```c++
> HINTERNET WINAPI InternetConnect(
> HINTERNET hInternet,
> LPCTSTR lpszServerName,
> INTERNET_PORT nServerPort,
> LPCTSTR lpszUserName,
> LPCTSTR lpszPassword,
> DWORD dwService,
> DWORD dwFlags,
> DWORD dwContext
> );
> ```
>
> 参数说明
> hInternet:由InternetOpen返回的句柄。
> lpszServerName:连接的ip或者主机名
> nServerPort:连接的端口。
> lpszUserName:用户名,如无置NULL。
> lpszPassword:密码,如无置NULL。
> dwService:使用的服务类型,可以使用以下
>
> - INTERNET_SERVICE_FTP = 1:连接到一个 FTP 服务器上
> - INTERNET_SERVICE_GOPHER = 2
> - INTERNET_SERVICE_HTTP = 3:连接到一个 HTTP 服务器上
>
> dwFlags:文档传输形式及缓存标记。一般置0。
> dwContext:当使用回叫信号时, 用来识别应用程序的前后关系。
> 返回值
> 成功返回非0。如果返回0。要InternetCloseHandle释放这个句柄。
## 3. HttpOpenRequest介绍
> 函数声明
>
> ```c++
> HINTERNET HttpOpenRequest(
> _In_ HINTERNET hConnect,
> _In_ LPCTSTR lpszVerb,
> _In_ LPCTSTR lpszObjectName,
> _In_ LPCTSTR lpszVersion,
> _In_ LPCTSTR lpszReferer,
> _In_ LPCTSTR *lplpszAcceptTypes,
> _In_ DWORD dwFlags,
> _In_ DWORD_PTR dwContext
> );
> ```
>
> 参数
>
> hConnect:由InternetConnect返回的句柄。
>
> lpszVerb:一个指向某个包含在请求中要用的动词的字符串指针。如果为NULL,则使用“GET”。
>
> lpszObjectName:一个指向某个包含特殊动词的目标对象的字符串的指针。通常为文件名称、可执行模块或者查找标识符。
>
> lpszVersion:一个指向以null结尾的字符串的指针,该字符串包含在请求中使用的HTTP版本,Internet Explorer中的设置将覆盖该参数中指定的值。如果此参数为NULL,则该函数使用1.1或1.0的HTTP版本,这取决于Internet Explorer设置的值。
>
> lpszReferer:一个指向指定了包含着所需的URL (pstrObjectName)的文档地址(URL)的指针。如果为NULL,则不指定HTTP头。
>
> lplpszAcceptTypes:一个指向某空终止符的字符串的指针,该字符串表示客户接受的内容类型。如果该字符串为NULL,服务器认为客户接受“text/*”类型的文档 (也就是说,只有纯文本文档,并且不是图片或其它二进制文件)。内容类型与CGI变量CONTENT_TYPE相同,该变量确定了要查询的含有相关信息的数据的类型,如HTTP POST和PUT。
>
> dwFlags:dwFlags的值可以是下面一个或者多个。
>
> | 价值 | 说明 |
> | -------------------------------------- | ---------------------------------------- |
> | INTERNET_FLAG_DONT_CACHE | 不缓存的数据,在本地或在任何网关。 相同的首选值INTERNET_FLAG_NO_CACHE_WRITE。 |
> | INTERNET_FLAG_EXISTING_CONNECT | 如果可能的话,重用现有的连接到每个服务器请求新的请求而产生的**InternetOpenUrl**创建一个新的会话。 这个标志是有用的,只有对FTP连接,因为FTP是唯一的协议,通常在同一会议执行多个操作。 在Win 32 API的缓存一个单一的Internet连接句柄为每个[HINTERNET](http://translate.googleusercontent.com/translate_c?hl=zh-CN&sl=en&u=http://msdn.microsoft.com/en-us/library/ms903345.aspx&prev=/search%3Fq%3DiNTERNET_FLAG%26hl%3Dzh-CN%26safe%3Dstrict%26sa%3DG%26prmd%3Divns&rurl=translate.google.com.hk&usg=ALkJrhhwr4QHQApAUuTng3WoiRljfyZSNA)处理产生的**InternetOpen。** |
> | INTERNET_FLAG -超链接 | 强制重载如果没有到期的时间也没有最后修改时间从服务器在决定是否加载该项目从网络返回。 |
> | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | 禁用的Win32上网功能的SSL /厘为基础的打击是从给定的请求服务器返回的主机名称证书检查。 Win32的上网功能用来对付证书由匹配主机名和HTTP请求一个简单的通配符规则比较简单的检查。 |
> | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | 禁用的Win32上网功能的SSL /厘为基础的HTTP请求适当的日期,证书的有效性检查。 |
> | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | 禁用的Win32上网功能能够探测到这种特殊类型的重定向。 当使用此标志,透明的Win32上网功能允许对HTTP重定向的URL从HTTPS。 |
> | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | 禁用的Win32上网功能能够探测到这种特殊类型的重定向。 当使用此标志,透明的Win32上网功能允许从HTTP重定�