在C++中使用Windows API发送HTTP GET请求

在网上找了很多文章,但基本都是说,C++发送HTTP请求可以,但谈到具体方法,就众说众说纷纭了。具体说来,有IXMLHTTPRequest2、curl、POCO,当然还有用socket、Windows API的方法。这些方法中,除了socket外,我都尝试过。

首先我用的是curl,需要先编译,编译完成后,就可以用curl_xxx的函数来发送和接收请求了,但是马上我就发现了一个问题,必须使用动态链接库才能运行,即使我编译好了静态库,还指定了/MT(而不是/MD),也不行。非常的尴尬,本来应该是一个跨平台的完美解决方案,但就因为这样一个愚蠢的原因,就没探索了。

然后我尝试使用COM组件,需要用到<MsXml6.h>头文件和<MsXml6.lib>库,网上有IXMLHTTPRequest2的例子,但例子是Windows Store上的应用,语法也是C++/CX,部分代码还用到了.NET里面的东西(虽然我相信可以不需要.NET),移植了一阵子后,感觉很麻烦,就换方法了。

再然后我发现POCO库可以解决这个问题,当准备用POCO库的时候,发现也需要编译,就想到了以前编译curl和gmp后的结果(静态库总有这样或那样的问题,动态库正常),然后直接没信心再试了。

最后我使用了Windows API,用的<winhttp.h>头文件,配合使用winhttp.lib库,成功,而且感觉,只需封装一下,这是我想要的方法:

// CppConsole.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <winhttp.h>
#pragma comment(lib, "winhttp")

using namespace std;

void do_work();

int _tmain(int argc, _TCHAR* argv[])
{
    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
    do_work();
}

void do_work()
{
    DWORD dwSize = 0;
    DWORD dwDownloaded = 0;
    LPSTR pszOutBuffer;
    BOOL bResults = FALSE;
    HINTERNET hSession = NULL, 
              hConnect = NULL, 
              hRequest = NULL;

    // Use WinHttpOpen to obtain a session handle.
    hSession = WinHttpOpen(L"A WinHTTP Example Program/1.0", 
                           WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 
                           WINHTTP_NO_PROXY_NAME, 
                           WINHTTP_NO_PROXY_BYPASS, 0);

    // Specify an HTTP server
    if (hSession)
        hConnect = WinHttpConnect(hSession, L"baidu.com", 
                                  INTERNET_DEFAULT_HTTP_PORT, 0);

    // Create an HTTP Request handle.
    if (hConnect)
        hRequest = WinHttpOpenRequest(hConnect, L"GET", 
                                      L"", 
                                      NULL, WINHTTP_NO_REFERER, 
                                      WINHTTP_DEFAULT_ACCEPT_TYPES, 
                                      0);

    // Send a Request.
    if (hRequest)
        bResults = WinHttpSendRequest(hRequest, 
                                      WINHTTP_NO_ADDITIONAL_HEADERS, 
                                      0, WINHTTP_NO_REQUEST_DATA, 0, 
                                      0, 0);

    // End the request.
    if (bResults)
        bResults = WinHttpReceiveResponse(hRequest, NULL);

    // Continue to verify data until there is nothing left.
    if (bResults)
    {
        do
        {
            // Verify available data.
            dwSize = 0;
            if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
                printf("Error %u in WinHttpQueryDataAvailable.\n", 
                       GetLastError());
            
            // Allocate space for the buffer.
            pszOutBuffer = new char[dwSize+1];
            
            // Read the Data.
            ZeroMemory(pszOutBuffer, dwSize+1);

            if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, 
                                 dwSize, &dwDownloaded))
                printf("Error %u in WinHttpReadData.\n", GetLastError());
            else
                printf("%s\n", pszOutBuffer);

            // Free the memory allocated to the buffer.
            delete[] pszOutBuffer;
        } while (dwSize > 0);
    } 

    // Report errors.
    if (!bResults)
        printf("Error %d has occurred.\n", GetLastError());

    // Close open handles.
    if (hRequest) WinHttpCloseHandle(hRequest);
    if (hConnect) WinHttpCloseHandle(hConnect);
    if (hSession) WinHttpCloseHandle(hSession);
}
View Code

 

posted @ 2013-06-14 13:17  .NET骚操作  阅读(9100)  评论(1编辑  收藏  举报