HTTP
基于下层的TCP传输,由Client和Server端组成,数据交换如下:
Client Server
请求数据包 -->
<-- 响应数据包
下面是一个wireshark抓包实例:

浅红色是请求,浅蓝色是响应。通过上面的http可以下载完整的一首 春天里
WinInet
WinInet是一个ms为了方便程序员开发而弄出来的一组winapi。
通过使用这组winapi使得程序员不必要去了解下层的winsocket及http、ftp协议的具体内容。
下面的只涉及到有关http部分。
对这组api分类:通用部分api函数、http相关api函数、ftp相关api函数。
使用这组函数的顺序如下(http):
创建Internet对话Session(InternetOpen)->创建到服务器的连接Connect(InternetConnect)
->创建http请求Request(HttpOpenRequest)->发送请求(HttpSendRequest)->关闭Request请求(InternetCloseHandle)
->关闭到服务器连接Connect(InternetCloseHandle)->关闭Internet对话Session(InternetCloseHandle)
在这组api中包含了3类句柄:Session(对话)、Connect(连接)、Request(请求)。类型都是HINTERNET
下面是对这组api参数解释。
创建Session
HINTERNET (
LPCTSTR
lpszAgent, //这个随便起个名字就行
DWORD
dwAccessType, //一般情况下都是INTERNET_OPEN_TYPE_PRECONFIG
LPCTSTR
lpszProxyName, //不使用代理,这里为NULL
LPCTSTR
lpszProxyBypass, //不使用代理,这里为NULL
DWORD
dwFlags); //同步情况下,这里为0
创建Conncet
HINTERNET InternetConnect(
HINTERNET hInternet, //上面创建的Session
LPCTSTR lpszServerName, //要请求的服务器名称,如字串 http://www.helloworld.com/
INTERNET_PORT nServerPort, //服务器服务端口号,这里一般都是80,选择INTERNET_DEFAULT_HTTP_PORT宏即可
LPCTSTR lpszUsername, //用户名,一般不需认证,使用NULL
LPCTSTR lpszPassword, //用户名,一般不需认证,使用NULL
DWORD dwService, //使用的服务名称,一般都是INTERNET_SERVICE_HTTP
DWORD dwFlags, //服务选项,一般都是0
DWORD_PTR dwContext //基本没什么作用
);
HINTERNET hInternet, //上面创建的Session
LPCTSTR lpszServerName, //要请求的服务器名称,如字串 http://www.helloworld.com/
INTERNET_PORT nServerPort, //服务器服务端口号,这里一般都是80,选择INTERNET_DEFAULT_HTTP_PORT宏即可
LPCTSTR lpszUsername, //用户名,一般不需认证,使用NULL
LPCTSTR lpszPassword, //用户名,一般不需认证,使用NULL
DWORD dwService, //使用的服务名称,一般都是INTERNET_SERVICE_HTTP
DWORD dwFlags, //服务选项,一般都是0
DWORD_PTR dwContext //基本没什么作用
);
创建Request
HINTERNET HttpOpenRequest(
HINTERNET hConnect, //上面创建的Connect
LPCTSTR lpszVerb, //表示Http的2种方法之一的字符串,"GET","PUT"一般选择"GET"即可
LPCTSTR lpszObjectName, //某个网站上面具体的某个文件完整路径如/index.html
LPCTSTR lpszVersion, //HTTP协议版本号,有HTTP1.0和HTTP1.1,在这里简单的选择HTTP_VERSION(HTTP1.0)即可
LPCTSTR lpszReferer, //说明上面lpszObjectName具体类型,这里一般选择NULL,表示不作指定
LPCTSTR* lpszAcceptTypes, //选择接受的文件类型,全部类型都进行接受,指定字串为:" */*",这个可以参考上面的请求数据包中的Accept
DWORD dwFlags, //进行特殊的选项设定,这里直接使用0不作选择
DWORD_PTR dwContext //这里没什么大作用,直接使用0
);
HINTERNET hConnect, //上面创建的Connect
LPCTSTR lpszVerb, //表示Http的2种方法之一的字符串,"GET","PUT"一般选择"GET"即可
LPCTSTR lpszObjectName, //某个网站上面具体的某个文件完整路径如/index.html
LPCTSTR lpszVersion, //HTTP协议版本号,有HTTP1.0和HTTP1.1,在这里简单的选择HTTP_VERSION(HTTP1.0)即可
LPCTSTR lpszReferer, //说明上面lpszObjectName具体类型,这里一般选择NULL,表示不作指定
LPCTSTR* lpszAcceptTypes, //选择接受的文件类型,全部类型都进行接受,指定字串为:" */*",这个可以参考上面的请求数据包中的Accept
DWORD dwFlags, //进行特殊的选项设定,这里直接使用0不作选择
DWORD_PTR dwContext //这里没什么大作用,直接使用0
);
发送Request
BOOL HttpSendRequest(
HINTERNET hRequest, //上面创建的Request
LPCTSTR lpszHeaders, //在这里可以按照自己需要添加特殊的Header,这里简单的只需参数0即可
DWORD dwHeadersLength, //上面Header参数的长度
LPVOID lpOptional, //这里可以添加一些option参数,这里简单的设置为0
DWORD dwOptionalLength //上面option参数的长度
);
HINTERNET hRequest, //上面创建的Request
LPCTSTR lpszHeaders, //在这里可以按照自己需要添加特殊的Header,这里简单的只需参数0即可
DWORD dwHeadersLength, //上面Header参数的长度
LPVOID lpOptional, //这里可以添加一些option参数,这里简单的设置为0
DWORD dwOptionalLength //上面option参数的长度
);
关闭InternetHandle
BOOL WINAPI InternetCloseHandle(
HINTERNET hInternet //包括了上的Session句柄,Connect句柄,Request句柄,都可以在这个函数中进行关闭
);
HINTERNET hInternet //包括了上的Session句柄,Connect句柄,Request句柄,都可以在这个函数中进行关闭
);
源码
#include <windows.h>
#include <WinInet.h>
#include <stdio.h>
#pragma comment(lib,"Wininet.lib")
#define BUFFER_SIZE 1024
static CHAR Buffer[BUFFER_SIZE];
TCHAR szMethod[] = TEXT("GET");
TCHAR szServerName[] = TEXT("www.itbusy.com");
TCHAR szForm[] = TEXT("/mp3/ctl.mp3");
INT main(VOID)
{
HINTERNET hSession;
HINTERNET hConnect;
HINTERNET hRequest;
BOOL bSendRequest;
// 创建Session
hSession = InternetOpen(TEXT("hello"),
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
// 创建Connect
hConnect = InternetConnect(hSession,
szServerName,
INTERNET_DEFAULT_HTTP_PORT,
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,
0);
// 创建Request
hRequest = HttpOpenRequest(hConnect,
szMethod,
szForm,
HTTP_VERSION,
NULL,
NULL,//(const TCHAR**)&szAcceptType,
0,
0);
// 发送Request
bSendRequest = HttpSendRequest(hRequest,
NULL,
0,
NULL,
0);
{
DWORD dwReadSize;
FILE* file;
if ((file = fopen("c:\\test.html", "wb+")) != NULL)
{
while(1)
{
InternetReadFile(hRequest, Buffer, BUFFER_SIZE, &dwReadSize);
if (dwReadSize == 0)
break;
fwrite(Buffer, 1, dwReadSize, file);
}
fclose(file);
}
}
//////////////////////////////////////////////////
// 清除InternetHandle
if (hRequest)
InternetCloseHandle(hRequest);
if (hConnect)
InternetCloseHandle(hConnect);
if (hSession)
InternetCloseHandle(hSession);
return 0;
}
在编译此源代码过程中,添加预定义宏_CRT_SECURE_NO_WARNINGS可以避免警告。