转自:http://www.cppblog.com/huyutian/articles/122994.html
关于WinInet的异步模式,微软给过很多例子,但我觉得下面这个是比较好理解的。
原文地址,代码贴出来,有些细节部分还要自己慢慢体会。
我在调试过程中,还参照了以下一些链接
关于GetLastError返回1201(ERROR_INTERNET_INCORRECT_HANDLE_STATE)9错误的解决办法请参见下面两个链接
http://support.genopro.com/Topic14017-59-1.aspx
http://support.microsoft.com/kb/177190
这是微软wininet的一个bug,仅当大 POST请求包要发送时,使用 HttpSendRequestEx。其他时候使用HttpSendRequest。防止12019错误
WinInet 错误代码可参照这里 http://support.microsoft.com/kb/193625
1
#include
<
windows.h
>
2
#include
<
wininet.h
>
3
#include
<
iostream.h
>
4
5
HANDLE hConnectedEvent, hRequestOpenedEvent, hRequestCompleteEvent;
6
HINTERNET hInstance, hConnect, hRequest;
7
char
*
lpszUrl,
*
lpszServer;
8
9
BOOL bAllDone
=
FALSE;
10
BOOL bVerbose
=
FALSE;
11
12
void
__stdcall Callback(HINTERNET hInternet,
13
DWORD dwContext,
14
DWORD dwInternetStatus,
15
LPVOID lpStatusInfo,
16
DWORD dwStatusInfoLen);
17
18
void
main(
int
argc,
char
*
argv[])
19
{
20
if (argc != 3)
21
{
22
if ((argc == 4) && (argv[3][0] == 'v'))
23
bVerbose = TRUE;
24
else
25
{
26
cout << "Usage: asynchttp <server> <url> [v]" << endl;
27
cout << " <server> is the hostname of the http server" << endl;
28
cout << " <url> is the url of the object you are requesting (without the hostname)" << endl;
29
cout << " 'v' for verbose output" << endl << endl;
30
cout << " Example: asynchttp www.domain.com /docs/readme.htm v" << endl;
31
return;
32
}
33
}
34
35
lpszServer = argv[1];
36
lpszUrl = argv[2];
37
38
hConnectedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
39
hRequestOpenedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
40
hRequestCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
41
42
hInstance = InternetOpen("asynchttp",
43
INTERNET_OPEN_TYPE_PRECONFIG,
44
NULL,
45
NULL,
46
INTERNET_FLAG_ASYNC); // ASYNC Flag
47
48
if (hInstance == NULL)
49
{
50
cout << "InternetOpen failed, error " << GetLastError();
51
return;
52
}
53
54
// Setup callback function
55
if (InternetSetStatusCallback(hInstance,
56
(INTERNET_STATUS_CALLBACK)&Callback) == INTERNET_INVALID_STATUS_CALLBACK)
57
{
58
cout << "InternetSetStatusCallback failed, error " << GetLastError();
59
return;
60
}
61
62
// First call that will actually complete asynchronously even
63
// though there is no network traffic
64
hConnect = InternetConnect(hInstance,
65
lpszServer,
66
INTERNET_DEFAULT_HTTP_PORT,
67
NULL,
68
NULL,
69
INTERNET_SERVICE_HTTP,
70
0,
71
1); // Connection handle's Context
72
if (hConnect == NULL)
73
{
74
if (GetLastError() != ERROR_IO_PENDING)
75
{
76
cout << "InternetConnect failed, error " << GetLastError();
77
return;
78
}
79
// Wait until we get the connection handle
80
WaitForSingleObject(hConnectedEvent, INFINITE);
81
}
82
83
84
// Open the request
85
hRequest = HttpOpenRequest(hConnect,
86
"GET",
87
lpszUrl,
88
NULL,
89
NULL,
90
NULL,
91
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE,
92
2); // Request handle's context
93
if (hRequest == NULL)
94
{
95
if (GetLastError() != ERROR_IO_PENDING)
96
{
97
cout << "HttpOpenRequest failed, error " << GetLastError();
98
return;
99
}
100
// Wait until we get the request handle
101
WaitForSingleObject(hRequestOpenedEvent, INFINITE);
102
}
103
104
if (!HttpSendRequest(hRequest,
105
NULL,
106
0,
107
NULL,
108
0))
109
{
110
if (GetLastError() != ERROR_IO_PENDING)
111
{
112
cout << "HttpSendRequest failed, error " << GetLastError();
113
return;
114
}
115
}
116
117
if (bVerbose)
118
{
119
cout << "HttpSendRequest called successfully" << endl;
120
cout.flush();
121
}
122
123
WaitForSingleObject(hRequestCompleteEvent, INFINITE);
124
125
cout << "------------------- Read the response -------------------" << endl;
126
char lpReadBuff[256];
127
128
do
129
{
130
INTERNET_BUFFERS InetBuff;
131
FillMemory(&InetBuff, sizeof(InetBuff), 0);
132
InetBuff.dwStructSize = sizeof(InetBuff);
133
InetBuff.lpvBuffer = lpReadBuff;
134
InetBuff.dwBufferLength = sizeof(lpReadBuff) - 1;
135
136
if (bVerbose)
137
{
138
cout << "Calling InternetReadFileEx" << endl;
139
cout.flush();
140
}
141
142
if (!InternetReadFileEx(hRequest,
143
&InetBuff,
144
0, 2))
145
{
146
if (GetLastError() == ERROR_IO_PENDING)
147
{
148
if (bVerbose)
149
{
150
cout << "Waiting for InternetReadFileEx to complete" << endl;
151
cout.flush();
152
}
153
WaitForSingleObject(hRequestCompleteEvent, INFINITE);
154
}
155
else
156
{
157
cout << "InternetReadFileEx failed, error " << GetLastError();
158
cout.flush();
159
return;
160
}
161
}
162
163
lpReadBuff[InetBuff.dwBufferLength] = 0;
164
cout << lpReadBuff;
165
cout.flush();
166
167
if (InetBuff.dwBufferLength == 0)
168
bAllDone = TRUE;
169
170
} while (bAllDone == FALSE);
171
172
cout << endl << endl << "------------------- Request Complete ----------------" << endl;
173
174
}
175
176
void
__stdcall Callback(HINTERNET hInternet,
177
DWORD dwContext,
178
DWORD dwInternetStatus,
179
LPVOID lpStatusInfo,
180
DWORD dwStatusInfoLen)
181
{
182
if (bVerbose)
183
{
184
cout << "Callback dwInternetStatus: " << dwInternetStatus << " Context: " << dwContext << endl;
185
cout.flush();
186
}
187
188
switch(dwContext)
189
{
190
case 1: // Connection handle
191
if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED)
192
{
193
INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
194
hConnect = (HINTERNET)pRes->dwResult;
195
if (bVerbose)
196
{
197
cout << "Connect handle created" << endl;
198
cout.flush();
199
}
200
SetEvent(hConnectedEvent);
201
}
202
break;
203
case 2: // Request handle
204
switch(dwInternetStatus)
205
{
206
case INTERNET_STATUS_HANDLE_CREATED:
207
{
208
INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
209
hRequest = (HINTERNET)pRes->dwResult;
210
if (bVerbose)
211
{
212
cout << "Request handle created" << endl;
213
cout.flush();
214
}
215
SetEvent(hRequestOpenedEvent);
216
}
217
break;
218
case INTERNET_STATUS_REQUEST_SENT:
219
{
220
DWORD *lpBytesSent = (DWORD*)lpStatusInfo;
221
if (bVerbose)
222
{
223
cout << "Bytes Sent: " << *lpBytesSent << endl;
224
cout.flush();
225
}
226
}
227
break;
228
case INTERNET_STATUS_REQUEST_COMPLETE:
229
{
230
INTERNET_ASYNC_RESULT *pAsyncRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
231
if (bVerbose)
232
{
233
cout << "Function call finished" << endl;
234
cout << "dwResult: " << pAsyncRes->dwResult << endl;
235
cout << "dwError: " << pAsyncRes->dwError << endl;
236
cout.flush();
237
}
238
SetEvent(hRequestCompleteEvent);
239
}
240
break;
241
case INTERNET_STATUS_RECEIVING_RESPONSE:
242
if (bVerbose)
243
{
244
cout << "Receiving Response" << endl;
245
cout.flush();
246
}
247
break;
248
case INTERNET_STATUS_RESPONSE_RECEIVED:
249
{
250
DWORD *dwBytesReceived = (DWORD*)lpStatusInfo;
251
if (*dwBytesReceived == 0)
252
bAllDone = TRUE;
253
if (bVerbose)
254
{
255
cout << "Received " << *dwBytesReceived << endl;
256
cout.flush();
257
}
258
}
259
260
}
261
262
}
263
264
}
265

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19



20

21



22

23

24

25



26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49



50

51

52

53

54

55

56

57



58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73



74

75



76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94



95

96



97

98

99

100

101

102

103

104

105

106

107

108

109



110

111



112

113

114

115

116

117

118



119

120

121

122

123

124

125

126

127

128

129



130

131

132

133

134

135

136

137



138

139

140

141

142

143

144

145



146

147



148

149



150

151

152

153

154

155

156



157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181



182

183



184

185

186

187

188

189



190

191

192



193

194

195

196



197

198

199

200

201

202

203

204

205



206

207



208

209

210

211



212

213

214

215

216

217

218

219



220

221

222



223

224

225

226

227

228

229



230

231

232



233

234

235

236

237

238

239

240

241

242

243



244

245

246

247

248

249



250

251

252

253

254



255

256

257

258

259

260

261

262

263

264

265
