您的位置:首页 > 理论基础 > 计算机网络

使用WinINet和WinHTTP实现Http访问

2007-11-30 19:21 549 查看
使用WinINetWinHTTP实现Http访问
飘飘白云 l_zhaohui@163.com 2007-11-30

Http访问有两种方式,GET和POST,就编程来说GET方式相对简单点,它不用向服务器提交数据,在这个例程中我使用POST方式,提交数据value1与value2,并从服务器得到他们的和(value1 + value2)。

为实现Http访问,微软提供了二套API:WinINet, WinHTTP。WinHTTP比WinINet更加安全和健壮,可以这么认为WinHTTP是WinINet的升级版本。这两套API包含了很多相似的函数与宏定义,呵呵,详细对比请查阅msdn中的文章“Porting WinINet Applications to WinHTTP”,在线MSDN连接:http://msdn2.microsoft.com/en-us/library/aa384068.aspx。在这个例程中,通过一个宏的设置来决定是使用WinHttp还是WinINet。代码如下:

#define USE_WINHTTP //Comment this line to user wininet.

下面来说说实现Http访问的流程(两套API都一样的流程):

1, 首先我们打开一个Session获得一个HINTERNET session句柄;

2, 然后我们使用这个session句柄与服务器连接得到一个HINTERNET connect句柄;

3, 这样我们使用这个connect句柄来打开Http 请求得到一个HINTERNET request句柄;

4, 这样我们就可以使用这个request句柄来发送数据与读取从服务器返回的数据;

5, 最后依次关闭request,connect,session句柄。



在这个例程中以上各个流程都进行了简单封装,以便对比两套API函数的些许差异。下面让源代码说话,原工程是一个windows控制台工程,你可以很容易通过拷贝代码重建工程。



另:如果你从服务器得到的返回数据是utf8格式的文本数据,你将需要对返回的数据进行转换才能争取显示(中文,日文等)。仅供参考,转换为ATL CStringW的函数见下:




CStringW GetStringWFromUtf8(const std::string& str)






{


int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), int(str.length()), 0, 0);




CStringW buf;


WCHAR* dd = buf.GetBuffer(len);




len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), int(str.length()), dd, len);




buf.ReleaseBuffer(len);




return buf;


}

完整代码如下:

1

// HttpPost.cpp written by l_zhaohui@163.com
2

// 2007/11/30
3

#include "stdafx.h"
4

#include <windows.h>
5

#include <stdio.h>
6

#include <stdlib.h>
7


8

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
9

#include <atlbase.h>
10

#include <atlstr.h>
11


12

#define USE_WINHTTP //Comment this line to user wininet.
13

#ifdef USE_WINHTTP
14

#include <winhttp.h>
15

#pragma comment(lib, "winhttp.lib")
16

#else
17

#include <wininet.h>
18

#pragma comment(lib, "wininet.lib")
19

#endif
20

#define BUF_SIZE (1024)
21


22

// CrackedUrl
23



class CrackedUrl

{
24

int m_scheme;
25

CStringW m_host;
26

int m_port;
27

CStringW m_path;
28

public:
29

CrackedUrl(LPCWSTR url)
30





{
31



URL_COMPONENTS uc =

{ 0};
32

uc.dwStructSize = sizeof(uc);
33


34

const DWORD BUF_LEN = 256;
35


36

WCHAR host[BUF_LEN];
37

uc.lpszHostName = host;
38

uc.dwHostNameLength = BUF_LEN;
39


40

WCHAR path[BUF_LEN];
41

uc.lpszUrlPath = path;
42

uc.dwUrlPathLength = BUF_LEN;
43


44

WCHAR extra[BUF_LEN];
45

uc.lpszExtraInfo = extra;
46

uc.dwExtraInfoLength = BUF_LEN;
47


48

#ifdef USE_WINHTTP
49



if (!WinHttpCrackUrl(url, 0, ICU_ESCAPE, &uc))

{
50

printf("Error:WinHttpCrackUrl failed!/n");
51

}
52


53

#else
54



if (!InternetCrackUrl(url, 0, ICU_ESCAPE, &uc))

{
55

printf("Error:InternetCrackUrl failed!/n");
56

}
57

#endif
58

m_scheme = uc.nScheme;
59

m_host = host;
60

m_port = uc.nPort;
61

m_path = path;
62

}
63


64

int GetScheme() const
65





{
66

return m_scheme;
67

}
68


69

LPCWSTR GetHostName() const
70





{
71

return m_host;
72

}
73


74

int GetPort() const
75





{
76

return m_port;
77

}
78


79

LPCWSTR GetPath() const
80





{
81

return m_path;
82

}
83


84

static CStringA UrlEncode(const char* p)
85





{
86



if (p == 0)

{
87

return CStringA();
88

}
89


90

CStringA buf;
91


92



for (;;)

{
93

int ch = (BYTE) (*(p++));
94



if (ch == '/0')

{
95

break;
96

}
97


98



if (isalnum(ch) || ch == '_' || ch == '-' || ch == '.')

{
99

buf += (char)ch;
100

}
101



else if (ch == ' ')

{
102

buf += '+';
103

}
104



else

{
105

char c[16];
106

wsprintfA(c, "%%%02X", ch);
107

buf += c;
108

}
109

}
110


111

return buf;
112

}
113

};
114


115

// CrackedUrl
116

HINTERNET OpenSession(LPCWSTR userAgent = 0)
117





{
118

#ifdef USE_WINHTTP
119

return WinHttpOpen(userAgent, NULL, NULL, NULL, NULL);;
120

#else
121

return InternetOpen(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
122

#endif
123

}
124


125

HINTERNET Connect(HINTERNET hSession, LPCWSTR serverAddr, int portNo)
126





{
127

#ifdef USE_WINHTTP
128

return WinHttpConnect(hSession, serverAddr, (INTERNET_PORT) portNo, 0);
129

#else
130

return InternetConnect(hSession, serverAddr, portNo, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
131

#endif
132

}
133


134

HINTERNET OpenRequest(HINTERNET hConnect, LPCWSTR verb, LPCWSTR objectName, int scheme)
135





{
136

DWORD flags = 0;
137

#ifdef USE_WINHTTP
138



if (scheme == INTERNET_SCHEME_HTTPS)

{
139

flags |= WINHTTP_FLAG_SECURE;
140

}
141


142

return WinHttpOpenRequest(hConnect, verb, objectName, NULL, NULL, NULL, flags);
143


144

#else
145



if (scheme == INTERNET_SCHEME_HTTPS)

{
146

flags |= INTERNET_FLAG_SECURE;
147

}
148


149

return HttpOpenRequest(hConnect, verb, objectName, NULL, NULL, NULL, flags, 0);
150

#endif
151

}
152


153

BOOL AddRequestHeaders(HINTERNET hRequest, LPCWSTR header)
154





{
155

SIZE_T len = lstrlenW(header);
156

#ifdef USE_WINHTTP
157

return WinHttpAddRequestHeaders(hRequest, header, DWORD(len), WINHTTP_ADDREQ_FLAG_ADD);
158

#else
159

return HttpAddRequestHeaders(hRequest, header, DWORD(len), HTTP_ADDREQ_FLAG_ADD);
160

#endif
161

}
162


163

BOOL SendRequest(HINTERNET hRequest, const void* body, DWORD size)
164





{
165

#ifdef USE_WINHTTP
166

return WinHttpSendRequest(hRequest, 0, 0, const_cast<void*>(body), size, size, 0);
167

#else
168

return HttpSendRequest(hRequest, 0, 0, const_cast<void*>(body), size);
169

#endif
170

}
171


172

BOOL EndRequest(HINTERNET hRequest)
173





{
174

#ifdef USE_WINHTTP
175

return WinHttpReceiveResponse(hRequest, 0);
176

#else
177

// if you use HttpSendRequestEx to send request then use HttpEndRequest in here!
178

return TRUE;
179

#endif
180

}
181


182

BOOL QueryInfo(HINTERNET hRequest, int queryId, char* szBuf, DWORD* pdwSize)
183





{
184

#ifdef USE_WINHTTP
185

return WinHttpQueryHeaders(hRequest, (DWORD) queryId, 0, szBuf, pdwSize, 0);
186

#else
187

return HttpQueryInfo(hRequest, queryId, szBuf, pdwSize, 0);
188

#endif
189

}
190


191

BOOL ReadData(HINTERNET hRequest, void* buffer, DWORD length, DWORD* cbRead)
192





{
193

#ifdef USE_WINHTTP
194

return WinHttpReadData(hRequest, buffer, length, cbRead);
195

#else
196

return InternetReadFile(hRequest, buffer, length, cbRead);
197

#endif
198

}
199


200

void CloseInternetHandle(HINTERNET hInternet)
201





{
202

if (hInternet)
203





{
204

#ifdef USE_WINHTTP
205

WinHttpCloseHandle(hInternet);
206

#else
207

InternetCloseHandle(hInternet);
208

#endif
209

}
210

}
211


212

int _tmain(int argc, _TCHAR* argv[])
213





{
214

HINTERNET hSession = 0;
215

HINTERNET hConnect = 0;
216

HINTERNET hRequest = 0;
217

CStringW strHeader(L"Content-type: application/x-www-form-urlencoded/r/n");
218


219

// Test data
220

CrackedUrl crackedUrl(L"http://www.easy-creator.net/test2/add.asp");
221

CStringA strPostData("value1=10&value2=14");
222


223

// Open session.
224

hSession = OpenSession(L"HttpPost by l_zhaohui@163.com");
225



if (hSession == NULL)

{
226

printf("Error:Open session!/n");
227

return -1;
228

}
229


230

// Connect.
231

hConnect = Connect(hSession, crackedUrl.GetHostName(), crackedUrl.GetPort());
232



if (hConnect == NULL)

{
233

printf("Error:Connect failed!/n");
234

return -1;
235

}
236


237

// Open request.
238

hRequest = OpenRequest(hConnect, L"POST", crackedUrl.GetPath(), crackedUrl.GetScheme());
239



if (hRequest == NULL)

{
240

printf("Error:OpenRequest failed!/n");
241

return -1;
242

}
243


244

// Add request header.
245



if (!AddRequestHeaders(hRequest, strHeader))

{
246

printf("Error:AddRequestHeaders failed!/n");
247

return -1;
248

}
249


250

// Send post data.
251



if (!SendRequest(hRequest, (const char*)strPostData, strPostData.GetLength()))

{
252

printf("Error:SendRequest failed!/n");
253

return -1;
254

}
255


256

// End request
257



if (!EndRequest(hRequest))

{
258

printf("Error:EndRequest failed!/n");
259

return -1;
260

}
261


262

char szBuf[BUF_SIZE];
263

DWORD dwSize = 0;
264

szBuf[0] = 0;
265


266

// Query header info.
267

#ifdef USE_WINHTTP
268

int contextLengthId = WINHTTP_QUERY_CONTENT_LENGTH;
269

int statusCodeId = WINHTTP_QUERY_STATUS_CODE;
270

int statusTextId = WINHTTP_QUERY_STATUS_TEXT;
271

#else
272

int contextLengthId = HTTP_QUERY_CONTENT_LENGTH;
273

int statusCodeId = HTTP_QUERY_STATUS_CODE;
274

int statusTextId = HTTP_QUERY_STATUS_TEXT;
275

#endif
276

dwSize = BUF_SIZE;
277



if (QueryInfo(hRequest, contextLengthId, szBuf, &dwSize))

{
278

szBuf[dwSize] = 0;
279

printf("Content length:[%s]/n", szBuf);
280

}
281


282

dwSize = BUF_SIZE;
283



if (QueryInfo(hRequest, statusCodeId, szBuf, &dwSize))

{
284

szBuf[dwSize] = 0;
285

printf("Status code:[%s]/n", szBuf);
286

}
287


288

dwSize = BUF_SIZE;
289



if (QueryInfo(hRequest, statusTextId, szBuf, &dwSize))

{
290

szBuf[dwSize] = 0;
291

printf("Status text:[%s]/n", szBuf);
292

}
293


294

// read data.
295



for (;;)

{
296

dwSize = BUF_SIZE;
297



if (ReadData(hRequest, szBuf, dwSize, &dwSize) == FALSE)

{
298

break;
299

}
300


301



if (dwSize <= 0)

{
302

break;
303

}
304


305

szBuf[dwSize] = 0;
306

printf("%s/n", szBuf); //Output value = value1 + value2
307

}
308


309

CloseInternetHandle(hRequest);
310

CloseInternetHandle(hConnect);
311

CloseInternetHandle(hSession);
312


313

return 0;
314

}
315
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: