Windows has a set of WinINet functions (http://msdn.microsoft.com/en-us/library/aa385473 (v = VS.85 ). aspx), the function about sending/receiving requests to the Internet is strange, especially the HttpSendRequest function is strange. The following is a sample code (the Code only analyzes the problem but does not find the cause)
This set of test code assumes that the network is normal.
1. BOOL SendHttpHeaderTest ()
2 .{
3. BOOL bRet = FALSE;
4. if (ERROR_SUCCESS! =: InternetAttemptConnect (0 ))
5. return FALSE;
6.
7. if (! : InternetCheckConnection (_ T ("http://www.baidu.com"), FLAG_ICC_FORCE_CONNECTION, 0 ))
8. return FALSE;
9.
10. TCHAR szModuleFile [MAX_PATH] = {0 };
11.: GetModuleFileName (: GetInstance (), szModuleFile, MAX_PATH );
12. LPCTSTR lpPath =: PathFindFileName (szModuleFile );
13. HINTERNET hOpen =: InternetOpen (lpPath, INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY, NULL, NULL, 0 );
14. DWORD dwErr =: GetLastError (); // return 0
15.
16. HINTERNET hConnect =: InternetConnect (hOpen, _ T ("www.baidu.com"), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 );
17. dwErr =: GetLastError (); // 0 is returned.
18.
19. # if 1
20. DWORD dwFlag = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_AUTO_REDIRECT | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES;
21. HINTERNET hOpenRequest =: HttpOpenRequest (hConnect, _ T ("GET"), _ T ("img/baidu_sylogo1.gif"), _ T ("HTTP/1.1 "), _ T ("http://www.baidu.com/"), NULL, dwFlag, 0 );
22. dwErr =: GetLastError (); // 122 is returned.
23.
24.
25. bRet =: HttpSendRequest (hOpenRequest, NULL, 0, NULL, 0 );
26. dwErr =: GetLastError (); // return 0
27. # endif
28.
29. TCHAR szBuff [BUFF_LEN_1024] = {0 };
30. DWORD dwBuffSize = BUFF_LEN_1024;
31. bRet =: HttpQueryInfo (hOpenRequest, HTTP_QUERY_STATUS_CODE, (LPVOID) szBuff, & dwBuffSize, NULL );
32. dwErr =: GetLastError (); // return 0
33.
34. // Reference to http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
35. int nStatusCode = _ tstoi (szBuff); // The value is, indicating that the request data baidu_sylogo1.gif is successful.
36. if (nStatusCode <200 | 206 <nStatusCode)
37. bRet = FALSE;
38.
39. bRet = TRUE;
40.: InternetCloseHandle (hConnect );
41.
42.: InternetCloseHandle (hOpen );
43.
44. return bRet;
45 .}
# If 1... # endif httpopenrequestto request baidu_sylogo1.gif from www.baidu.com, but this function does not send any data to www.baidu.com. This request is sent only when HttpSendRequest is called.
The Return Value of the HttpOpenRequest function is very interesting. It can be seen that its return value is valid, which proves that the call to the function is successful, but the returned value of dwErr is 122. Its meaning is ERROR_INSUFFICIENT_BUFFER: the data area passed to a system call is too small, but I do not know what it means or how to make dwErr 0.
According to the description in msdn, this code can be replaced with the following code:
1. # if 2
2. HINTERNET hOpenRequest =: HttpOpenRequest (hConnect, NULL, dwFlag, 0 );
3. dwErr =: GetLastError (); // still returns 122
4.
5. LPCTSTR lpHeader =
6. _ T ("GET/img/baidu_sylogo1.gif/HTTP/1.1")/A line
7. _ T ("Referer: http://www.baidu.com/?r=n") // B line
8. _ T ("Host: www.baidu.com") // C line
9. _ T ("\ r \ n"); // D line
10.
11. bRet =: HttpSendRequest (hOpenRequest, NULL, 0, NULL, 0 );
12. dwErr =: GetLastError (); // 0 is returned.
13. # endif
14. // observe the value of lpHeaer, which has the following features: 1) the end of line D has two "\ r \ n"; 2) line A does not end with \ r \ n; 3) line B ends with \ r \ n; 4) line C does not end with \ r \ n.
15. // Below we will test which of the four features will affect the call of HttpSendRequest.
16. Test1: // The end of line A is \ r \ n
17. LPCTSTR lpHeader = _ T ("GET/img/baidu_sylogo1.gif/HTTP/1.1 \ r \ n") _ T ("Referer: http://www.baidu.com/") _ T ("Host: www.baidu.com ") _ T (" \ r \ n ");
18. // HttpSendRequest returns 0, dwErr = 12150, meaning ERROR_HTTP_HEADER_NOT_FOUND: The requested header cocould not be located.
19. Test2: // A/B/C does not end with \ r \ n
20. LPCTSTR lpHeader = _ T ("GET/img/baidu_sylogo1.gif/HTTP/1.1") _ T ("Referer: http://www.baidu.com/") _ T ("Host: www.baidu.com ") _ T ("\ r \ n ");
21. // HttpSendRequest returns 1, dwErr = 0
22. Test3: // The end of line D is \ r \ n
23. LPCTSTR lpHeader = _ T ("GET/img/baidu_sylogo1.gif/HTTP/1.1") _ T ("Referer: http://www.baidu.com/") _ T ("Host: www.baidu.com ") _ T ("\ r \ n ");
24. // HttpSendRequest returns 1, dwErr = 0
25. Test4: // The end of line D is not \ r \ n
26. LPCTSTR lpHeader = _ T ("GET/img/baidu_sylogo1.gif/HTTP/1.1") _ T ("Referer: http://www.baidu.com/") _ T ("Host: www.baidu.com ");
27. // HttpSendRequest returns 1, dwErr = 0
From the above four tests, we can see that the second header of HttpSendRequest is A string, and line A must not have \ r \ n. Other rows can have or cannot have.
In the test, we also found that only line A causes the call of HttpSendRequest to fail and line B is required.
In fact, line A of the lpHeader value corresponds to the lpszVerb, lpszObjectName, and lpszVersion parameters of HttpOpenRequest. Line B corresponds to the lpszReferer parameter. Therefore, # if 2... endif can also be replaced by the following code:
1. # if 3
2. hOpenRequestHandle =: HttpOpenRequest (hConnectHandle, NULL, dwFlag, dwContext );
3. LPCTSTR lpHeader = _ T ("GET/img/baidu_sylogo1.gif/HTTP/1.1") _ T ("Referer: http://www.baidu.com /");
4. DWORD dwLen = _ tcslen (lpHeader );
5. bRet =: HttpAddRequestHeaders (hOpenRequestHandle, lpHeader, nLen, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD); // return 1
6. bRet =: HttpSendRequest (hOpenRequestHandle, NULL, 0, NULL, 0); // return 1
7. # endif
These tests are all tested in the VS2008 system. If anyone finds the HTTP header structure document sent by HttpSendRequest and other features, please let me know. I am very grateful.