zoukankan      html  css  js  c++  java
  • C++ http

    C++调用HTTP实现方式

    Http访问有两种方式,GET和POST,就编程来说GET方式相对简单点,它不用向服务器提交数据,程序中使用POST方式,
    提交数据并从服务器获取返回值。

    为实现Http访问,微软提供了二套API:WinINet, WinHTTP。WinHTTP比WinINet更加安全和健壮,可以这么认为WinHTTP是WinINet的升级版本。
    程序中,通过一个宏的设置来决定是使用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句柄。

    /***********************定义HTTP发送所用方法***********************************/
    HINTERNET OpenSession(LPCWSTR userAgent = 0)
    {
    #ifdef USE_WINHTTP
        return WinHttpOpen(userAgent, NULL, NULL, NULL, NULL);;
    #else
        return InternetOpen(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    #endif
    }

    HINTERNET Connect(HINTERNET hSession, LPCWSTR serverAddr, int portNo)
    {
    #ifdef USE_WINHTTP
        return WinHttpConnect(hSession, serverAddr, (INTERNET_PORT) portNo, 0);
    #else
        return InternetConnect(hSession, serverAddr, portNo, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
    #endif
    }

    HINTERNET OpenRequest(HINTERNET hConnect, LPCWSTR verb, LPCWSTR objectName, int scheme)
    {
        DWORD flags = 0;
    #ifdef USE_WINHTTP
        if (scheme == INTERNET_SCHEME_HTTPS) {
            flags |= WINHTTP_FLAG_SECURE;
        }

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

    #else
        if (scheme == INTERNET_SCHEME_HTTPS) {
            flags |= INTERNET_FLAG_SECURE;
        }

        return HttpOpenRequest(hConnect, verb, objectName, NULL, NULL, NULL, flags, 0);
    #endif
    }

    BOOL AddRequestHeaders(HINTERNET hRequest, LPCWSTR header)
    {
        SIZE_T len = lstrlenW(header);
    #ifdef USE_WINHTTP
        return WinHttpAddRequestHeaders(hRequest, header, DWORD(len), WINHTTP_ADDREQ_FLAG_ADD);
    #else
        return HttpAddRequestHeaders(hRequest, header, DWORD(len), HTTP_ADDREQ_FLAG_ADD);
    #endif
    }

    BOOL SendRequest(HINTERNET hRequest, const void* body, DWORD size)
    {
    #ifdef USE_WINHTTP
        return WinHttpSendRequest(hRequest, 0, 0, const_cast<void*>(body), size, size, 0);
    #else
        return HttpSendRequest(hRequest, 0, 0, const_cast<void*>(body), size);
    #endif
    }

    BOOL EndRequest(HINTERNET hRequest)
    {
    #ifdef USE_WINHTTP
        return WinHttpReceiveResponse(hRequest, 0);
    #else
        // if you use HttpSendRequestEx to send request then use HttpEndRequest in here!
        return TRUE;
    #endif
    }

    BOOL QueryInfo(HINTERNET hRequest, int queryId, char* szBuf, DWORD* pdwSize)
    {
    #ifdef USE_WINHTTP
        return WinHttpQueryHeaders(hRequest, (DWORD) queryId, 0, szBuf, pdwSize, 0);
    #else
        return HttpQueryInfo(hRequest, queryId, szBuf, pdwSize, 0);
    #endif
    }

    BOOL ReadData(HINTERNET hRequest, void* buffer, DWORD length, DWORD* cbRead)
    {
    #ifdef USE_WINHTTP
        return WinHttpReadData(hRequest, buffer, length, cbRead);
    #else
        return InternetReadFile(hRequest, buffer, length, cbRead);
    #endif
    }

    void CloseInternetHandle(HINTERNET hInternet)
    {
        if (hInternet)
    {
    #ifdef USE_WINHTTP
            WinHttpCloseHandle(hInternet);
    #else
            InternetCloseHandle(hInternet);
    #endif
        }
    }

    /**********************************************************/
    ///通过Http方式发送短信
    string SendSMS_HTTP(const long ececcid,const string & password ,const string & msisdn, const string &smsContent)
    {
     string rtnStr ="-1";
        HINTERNET hSession = 0;
        HINTERNET hConnect = 0;
        HINTERNET hRequest = 0;
        wstring strHeader(L"Content-type: application/x-www-form-urlencoded ");

        // Test data
        CrackedUrl crackedUrl(L"http://pi.f3.cn/SendSMS.aspx");
     string StrPostData = "ececcid=600000&password="+password+"&msisdn="+msisdn+"&smscontent="+smsContent+"&msgtype=5&longcode=";
     
     StrPostData = string_To_UTF8(StrPostData);

        // Open session.
        hSession = OpenSession(L"HttpPost by lyz_sea@163.com");
        if (hSession == NULL) {
            cout<<"Error:Open session! ";
            return "-1";
        }

        // Connect.
        hConnect = Connect(hSession, crackedUrl.GetHostName(), crackedUrl.GetPort());
        if (hConnect == NULL) {
            cout<<"Error:Connect failed! ";
            return "-1";
        }

        // Open request.
        hRequest = OpenRequest(hConnect, L"POST", crackedUrl.GetPath(), crackedUrl.GetScheme());
        if (hRequest == NULL) {
            cout<<"Error:OpenRequest failed! ";
            return "-1";
       }

        // Add request header.
     if (!AddRequestHeaders(hRequest, strHeader.c_str())) {
            cout<<"Error:AddRequestHeaders failed! ";
            return "-1";
        }

        // Send post data.
     if (!SendRequest(hRequest, StrPostData.c_str(), StrPostData.length())) {
            cout<<"Error:SendRequest failed! ";
            return "-1";
        }

        // End request
        if (!EndRequest(hRequest)) {
            cout<<"Error:EndRequest failed! ";
            return "-1";
        }

        char szBuf[BUF_SIZE];
        DWORD dwSize = 0;
        szBuf[0] = 0;

        // Query header info.
    #ifdef USE_WINHTTP
        int contextLengthId = WINHTTP_QUERY_CONTENT_LENGTH;
        int statusCodeId = WINHTTP_QUERY_STATUS_CODE;
        int statusTextId = WINHTTP_QUERY_STATUS_TEXT;
    #else
        int contextLengthId = HTTP_QUERY_CONTENT_LENGTH;
        int statusCodeId = HTTP_QUERY_STATUS_CODE;
        int statusTextId = HTTP_QUERY_STATUS_TEXT;
    #endif
        dwSize = BUF_SIZE;
        if (QueryInfo(hRequest, contextLengthId, szBuf, &dwSize)) {
            szBuf[dwSize] = 0;
            cout<<"Content length: "<<szBuf<<endl;
        }
        dwSize = BUF_SIZE;
        if (QueryInfo(hRequest, statusCodeId, szBuf, &dwSize)) {
            szBuf[dwSize] = 0;
            cout<<"Status code: "<< szBuf<<endl;
        }

        dwSize = BUF_SIZE;
        if (QueryInfo(hRequest, statusTextId, szBuf, &dwSize)) {
            szBuf[dwSize] = 0;
            cout<<"Status text:"<<szBuf<<endl;
        }

        // read data.
        for (;;) {
            dwSize = BUF_SIZE;
            if (ReadData(hRequest, szBuf, dwSize, &dwSize) == FALSE) {
               break;
            }

            if (dwSize <= 0) {
                break;
            }

            szBuf[dwSize] = 0;
            
      rtnStr =::UTF8_To_string(string(szBuf));

      cout<<rtnStr<<endl;//Output 返回值
       
        }

        CloseInternetHandle(hRequest);
        CloseInternetHandle(hConnect);
        CloseInternetHandle(hSession);

     return  rtnStr;
    }

    以上方法中用到的CrackURL方法在以下CrackURL.h文件中:

    #pragma once
    //#include<iostream>
    //using namespace std;

    #define USE_WINHTTP    //Comment this line to user wininet.
     #ifdef USE_WINHTTP
         #include <winhttp.h>
         #pragma comment(lib, "winhttp.lib")
     #else
         #include <wininet.h>
         #pragma comment(lib, "wininet.lib")
     #endif


     // CrackedUrl
     class CrackedUrl {
         int m_scheme;
         wstring m_host;
         int m_port;
         wstring m_path;
     public:
         CrackedUrl(LPCWSTR url)
         {
             URL_COMPONENTS uc = { 0};
             uc.dwStructSize = sizeof(uc);
     
             const DWORD BUF_LEN = 256;
     
             WCHAR host[BUF_LEN];
             uc.lpszHostName = host;
             uc.dwHostNameLength = BUF_LEN;
     
             WCHAR path[BUF_LEN];
             uc.lpszUrlPath = path;
             uc.dwUrlPathLength = BUF_LEN;
     
             WCHAR extra[BUF_LEN];
             uc.lpszExtraInfo = extra;
             uc.dwExtraInfoLength = BUF_LEN;
     
     #ifdef USE_WINHTTP
             if (!WinHttpCrackUrl(url, 0, ICU_ESCAPE, &uc)) {
                 cout<<"Error:WinHttpCrackUrl failed! ";
             }
     
     #else
             if (!InternetCrackUrl(url, 0, ICU_ESCAPE, &uc)) {
                 printf("Error:InternetCrackUrl failed! ");
             }
     #endif
             m_scheme = uc.nScheme;
             m_host = host;
             m_port = uc.nPort;
             m_path = path;
         }
     
         int GetScheme() const
         {
             return m_scheme;
         }
     
         LPCWSTR GetHostName() const
         {
       return m_host.c_str();
        }

        int GetPort() const
         {
             return m_port;
         }
     
         LPCWSTR GetPath() const
         {
       return m_path.c_str();
         }
     
         static string UrlEncode(const char* p)
         {
             if (p == 0) {
                 return string();
             }
     
             string buf;
     
            for (;;) {
                 int ch = (BYTE) (*(p++));
                 if (ch == '') {
                     break;
                 }
     
                 if (isalnum(ch) || ch == '_' || ch == '-' || ch == '.') {
                     buf += (char)ch;
                }
                else if (ch == ' ') {
                    buf += '+';
                }
                else {
                    char c[16];
                    wsprintfA(c, "%%%02X", ch);
                    buf += c;
                }
            }

            return buf;
        }
    };

  • 相关阅读:
    php环境配置中各个模块在网站建设中的功能
    PHP+Apache+MySQL+phpMyAdmin在win7系统下的环境配置
    August 17th 2017 Week 33rd Thursday
    August 16th 2017 Week 33rd Wednesday
    August 15th 2017 Week 33rd Tuesday
    August 14th 2017 Week 33rd Monday
    August 13th 2017 Week 33rd Sunday
    August 12th 2017 Week 32nd Saturday
    August 11th 2017 Week 32nd Friday
    August 10th 2017 Week 32nd Thursday
  • 原文地址:https://www.cnblogs.com/liangxiaofeng/p/5116273.html
Copyright © 2011-2022 走看看