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;
        }
    };

  • 相关阅读:
    maven POM.xml 标签详解
    Spring Boot Starter 的基本封装
    谷歌浏览器屏蔽广告的插件
    关于mysql中触发器old和new
    centos7 安装zookeeper3.4.8集群
    Flink架构、原理与部署测试
    图解Spark API
    汇编器构造
    Oracle11g CentOS7安装记录
    如何创造一门编程语言?
  • 原文地址:https://www.cnblogs.com/liangxiaofeng/p/5116273.html
Copyright © 2011-2022 走看看