程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> HttpSendRequest和Http頭

HttpSendRequest和Http頭

編輯:關於C語言

 

Windows中有一組WinINet函數(http://msdn.microsoft.com/en-us/library/aa385473(v=VS.85).aspx),其中關於向Internet發送/接受請求的函數比較奇怪,尤其是HttpSendRequest函數問題更是詭異,下面是代碼示例(該代碼只是分析出問題,但沒找到原因)

這組測試代碼假設網絡都是正常的.

 

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();//返回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

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

23.  

24.  

25.       bRet = ::HttpSendRequest(hOpenRequest, NULL, 0, NULL, 0);

26.       dwErr = ::GetLastError();//返回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();//返回0

33.  

34.       //Reference to http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

35.       int nStatusCode = _tstoi(szBuff);// 值為200,證明請求數據baidu_sylogo1.gif是成功的.

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 HttpOpenRequest說明要向www.baidu.com請求baidu_sylogo1.gif,但這個函數是不會向www.baidu.com發送任何數據的,只有調用HttpSendRequest時才會發送這個請求.

  HttpOpenRequest函數的返回值很有意思,可以看到它的返回值是有效的,證明對該函數的調用是成功的,但問題dwErr返回值是122,它的含義是ERROR_INSUFFICIENT_BUFFER: The data area passed to a system call is too small,但不知道什麼意思,也不知到如何才能使dwErr成為0.

  根據msdn中的描述,這段代碼可以用下面一段代碼替換:

 

1.    #if 2

2.        HINTERNET hOpenRequest = ::HttpOpenRequest(hConnect, NULL, NULL, NULL, NULL, NULL, dwFlag, 0);

3.        dwErr = ::GetLastError();//仍然返回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\r\n");                           //D line

10.  

11.       bRet = ::HttpSendRequest(hOpenRequest, NULL, 0, NULL, 0);

12.       dwErr = ::GetLastError();//返回0

13.   #endif

14.   // 注意觀察lpHeaer的值,有如下幾個特點:1)它的結尾D行有兩個"\r\n\r\n";2)A行結尾沒有\r\n;3)B行結尾有\r\n;4)C行結尾沒有\r\n.

15.   // 下面測試一下這4個特點究竟哪個會對HttpSendRequest的調用產生影響.

16.   Test1: // A行結尾有\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\r\n");

18.       // HttpSendRequest返回0, dwErr = 12150, 含義ERROR_HTTP_HEADER_NOT_FOUND:The requested header could not be located.

19.   Test2: // A/B/C行結尾沒有\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\r\n");

21.       // HttpSendRequest返回1, dwErr = 0

22.   Test3: // D行結尾一個\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返回1, dwErr = 0

25.   Test4: // D行結尾沒有\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返回1, dwErr = 0

 從以上4個測試可以看出,HttpSendRequest的第二個參數header是一個字符串,A行必須不能有\r\n,其它行可以有,也可以沒有.

 在測試中還發現,僅僅只有A行會導致HttpSendRequest調用失敗,必須得有B行.

 其實lpHeader的值A行剛好對應HttpOpenRequest的參數lpszVerb,lpszObjectName和lpszVersion;B行對應參數lpszReferer.所以,#if 2...endif 還可以用下面的代碼代替:

 

1.    #if 3

2.        hOpenRequestHandle = ::HttpOpenRequest(hConnectHandle, NULL, NULL, NULL, NULL, 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);//返回1

6.        bRet = ::HttpSendRequest(hOpenRequestHandle, NULL, 0, NULL, 0);//返回1

7.    #endif  

以上這些測試都是在VS2008系統中測試出來的,如果有誰發現HttpSendRequest發送的HTTP頭結構文檔及其它特點,還請告訴我,不勝感激

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved