zoukankan      html  css  js  c++  java
  • C++通过HTTP请求Get或Post方式请求Json数据

        最近在工作中,由于合作商只提供uRL,我这边需要通过HTTP请求Get或Post方式请求Json数据,然后解析JSON格式,解析json我使用的第三方库jsoncpp,代码如下

    #pragma once
    #include <iostream>
    #include <windows.h>
    #include <wininet.h>
    
    using namespace std;
    
    //每次读取的字节数
    #define READ_BUFFER_SIZE        4096
    
    enum HttpInterfaceError
    {
        Hir_Success = 0,        //成功
        Hir_InitErr,            //初始化失败
        Hir_ConnectErr,            //连接HTTP服务器失败
        Hir_SendErr,            //发送请求失败
        Hir_QueryErr,            //查询HTTP请求头失败
        Hir_404,                //页面不存在
        Hir_IllegalUrl,            //无效的URL
        Hir_CreateFileErr,        //创建文件失败
        Hir_DownloadErr,        //下载失败
        Hir_QueryIPErr,            //获取域名对应的地址失败
        Hir_SocketErr,            //套接字错误
        Hir_UserCancel,            //用户取消下载
        Hir_BufferErr,            //文件太大,缓冲区不足
        Hir_HeaderErr,            //HTTP请求头错误
        Hir_ParamErr,            //参数错误,空指针,空字符
        Hir_UnknowErr,
    };
    enum HttpRequest
    {
        Hr_Get,
        Hr_Post
    };
    class CWininetHttp
    {
    public:
        CWininetHttp(void);
        ~CWininetHttp(void);
    
    public:
        //  通过HTTP请求:Get或Post方式获取JSON信息 [3/14/2017/shike]
        const std::string RequestJsonInfo( const std::string& strUrl,
                                    HttpRequest type = Hr_Get, 
                                     std::string lpHeader = "",
                                     std::string lpPostData = "");
    protected:
        // 解析卡口Json数据 [3/14/2017/shike]
        void ParseJsonInfo(const std::string &strJsonInfo);
    
        // 关闭句柄 [3/14/2017/shike]
        void Release();
    
        // 释放句柄 [3/14/2017/shike]
        void ReleaseHandle( HINTERNET& hInternet );
    
        // 解析URL地址 [3/14/2017/shike]
        void ParseURLWeb( std::string strUrl, std::string& strHostName, std::string& strPageName, WORD& sPort);
    
        // UTF-8转为GBK2312 [3/14/2017/shike]
        char* UtfToGbk(const char* utf8);
    
    private:
        HINTERNET            m_hSession;
        HINTERNET            m_hConnect;
        HINTERNET            m_hRequest;
        HttpInterfaceError    m_error;
    };
    /*************************************************
    File name  :  WininetHttp.cpp
    Description:  通过URL访问HTTP请求方式获取JSON
    Author     :  shike
    Version    :  1.0
    Date       :  2016/10/27
    Copyright (C) 2016 -  All Rights Reserved
    *************************************************/
    #include "WininetHttp.h"
    //#include "Common.h"
    #include <json/json.h>
    #include <fstream>
    #include "common/CVLog.h"
    #pragma comment(lib, "Wininet.lib")
    #include <tchar.h>
    using namespace std;
    
    extern CCVLog CVLog;
    
    CWininetHttp::CWininetHttp(void):m_hSession(NULL),m_hConnect(NULL),m_hRequest(NULL)
    {
    }
    
    CWininetHttp::~CWininetHttp(void)
    {
        Release();
    }
    
    //  通过HTTP请求:Get或Post方式获取JSON信息 [3/14/2017/shike]
    const std::string CWininetHttp::RequestJsonInfo(const std::string& lpUrl,
                                                    HttpRequest type/* = Hr_Get*/,
                                                    std::string strHeader/*=""*/,
                                                    std::string strPostData/*=""*/)
    {
        std::string strRet = "";
        try
        {
            if ( lpUrl.empty())
            {
                throw Hir_ParamErr;
            }
            Release();
            m_hSession = InternetOpen(_T("Http-connect"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL);    //局部
    
            if ( NULL == m_hSession )
            {
                throw Hir_InitErr;
            }
    
            INTERNET_PORT port    = INTERNET_DEFAULT_HTTP_PORT;
            std::string strHostName = "";
            std::string strPageName = "";
    
            ParseURLWeb(lpUrl, strHostName, strPageName, port);
            printf("lpUrl:%s,
    strHostName:%s,
    strPageName:%s,
    port:%d
    ",lpUrl.c_str(),strHostName.c_str(),strPageName.c_str(),(int)port);
    
            m_hConnect = InternetConnectA(m_hSession, strHostName.c_str(), port, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, NULL);
    
            if ( NULL == m_hConnect )
            {
                throw Hir_ConnectErr;
            }
    
            std::string strRequestType;
            if ( Hr_Get == type )
            {
                strRequestType = "GET";
            }
            else
            {
                strRequestType = "POST";
            }
    
            m_hRequest = HttpOpenRequestA(m_hConnect,strRequestType.c_str(), strPageName.c_str(),"HTTP/1.1", NULL, NULL, INTERNET_FLAG_RELOAD, NULL);
            if ( NULL == m_hRequest )
            {
                throw Hir_InitErr;
            }
    
            DWORD dwHeaderSize = (strHeader.empty()) ? 0 : strlen(strHeader.c_str());
            BOOL bRet = FALSE;
            if ( Hr_Get == type )
            {
                bRet = HttpSendRequestA(m_hRequest,strHeader.c_str(),dwHeaderSize,NULL, 0);
            }
            else
            {
                DWORD dwSize = (strPostData.empty()) ? 0 : strlen(strPostData.c_str());
                bRet = HttpSendRequestA(m_hRequest,strHeader.c_str(),dwHeaderSize,(LPVOID)strPostData.c_str(), dwSize);
            }
            if ( !bRet )
            {
                throw Hir_SendErr;
            }
    
            char szBuffer[READ_BUFFER_SIZE + 1] = {0};
            DWORD dwReadSize = READ_BUFFER_SIZE;
            if ( !HttpQueryInfoA(m_hRequest, HTTP_QUERY_RAW_HEADERS, szBuffer, &dwReadSize, NULL) )
            {
                throw Hir_QueryErr;
            }
            if ( NULL != strstr(szBuffer, "404") )
            {
                throw Hir_404;
            }
    
            while( true )
            {
                bRet = InternetReadFile(m_hRequest, szBuffer, READ_BUFFER_SIZE, &dwReadSize);
                if ( !bRet || (0 == dwReadSize) )
                {
                    break;
                }
                szBuffer[dwReadSize]='';
                strRet.append(szBuffer);
            }
        }
        catch(HttpInterfaceError error)
        {
            m_error = error;
        }
        return std::move(strRet);
    }
    
    // 解析Json数据 [11/8/2016/shike]
    void CWininetHttp::ParseJsonInfo(const std::string &strJsonInfo)
    {
        Json::Reader reader;                                    //解析json用Json::Reader
        Json::Value value;                                        //可以代表任意类型
        if (!reader.parse(strJsonInfo, value))  
        {  
            CVLog.LogMessage(LOG_LEVEL_ERROR,"[CXLDbDataMgr::GetVideoGisData] Video Gis parse data error...");
        }
        if (!value["result"].isNull())        
        {
            int nSize = value["result"].size();
            for(int nPos = 0; nPos < nSize; ++nPos)                //对数据数组进行遍历
            {
                //PGCARDDEVDATA stru ;
                //stru.strCardName        = value["result"][nPos]["tollgateName"].asString();
                //stru.strCardCode        = value["result"][nPos]["tollgateCode"].asString();
                //std::string strCDNum    = value["result"][nPos]["laneNumber"].asString();    //增加:车道总数
                //stru.nLaneNum            = atoi(strCDNum.c_str());
                //std::string strLaneDir    = value["result"][nPos]["laneDir"].asString();        //增加:车道方向,进行规则转换
                //stru.strLaneDir            = TransformLaneDir(strLaneDir);
                //stru.dWgs84_x            = value["result"][nPos]["wgs84_x"].asDouble();
                //stru.dWgs84_y            = value["result"][nPos]["wgs84_y"].asDouble();
                //stru.dMars_x            = value["result"][nPos]["mars_x"].asDouble();
                //stru.dMars_y            = value["result"][nPos]["mars_y"].asDouble();
                //lstCardDevData.emplace_back(stru);
            }
        }
    }
    
    // 解析URL地址 [3/14/2017/shike]
    void CWininetHttp::ParseURLWeb( std::string strUrl, std::string& strHostName, std::string& strPageName, WORD& sPort)
    {
        sPort = 80;
        string strTemp(strUrl);
        std::size_t nPos = strTemp.find("http://");
        if (nPos != std::string::npos)
        {
            strTemp = strTemp.substr(nPos + 7, strTemp.size() - nPos - 7);
        }
    
        nPos = strTemp.find('/');
        if ( nPos == std::string::npos )    //没有找到
        {
            strHostName = strTemp;
        }
        else
        {
            strHostName = strTemp.substr(0, nPos);
        }
    
        std::size_t nPos1 = strHostName.find(':');
        if ( nPos1 != std::string::npos )
        {
            std::string strPort = strTemp.substr(nPos1 + 1, strHostName.size() - nPos1 - 1);
            strHostName = strHostName.substr(0, nPos1);
            sPort = (WORD)atoi(strPort.c_str());
        }
        if ( nPos == std::string::npos )
        {
            return ;
        }
        strPageName = strTemp.substr(nPos, strTemp.size() - nPos);
    }
    
    // 关闭句柄 [3/14/2017/shike]
    void CWininetHttp::Release()
    {
        ReleaseHandle(m_hRequest); 
        ReleaseHandle(m_hConnect); 
        ReleaseHandle(m_hSession);
    }
    
    // 释放句柄 [3/14/2017/shike]
    void CWininetHttp::ReleaseHandle( HINTERNET& hInternet )
    {
        if (hInternet) 
        { 
            InternetCloseHandle(hInternet); 
            hInternet = NULL; 
        }
    }
    
    // UTF-8转为GBK2312 [3/14/2017/shike]
    char* CWininetHttp::UtfToGbk(const char* utf8)
    {
        int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
        wchar_t* wstr = new wchar_t[len+1];
        memset(wstr, 0, len+1);
        MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
        len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
        char* str = new char[len+1];
        memset(str, 0, len+1);
        WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
        if(wstr) delete[] wstr;
        return str;
    }

    WinInet实现的HTTP接口/WinHttp实现的HTTP接口/Socket实现的HTTP接口/下载文件,使用回调接口获取下载进度,这些代码可以在开源中获取到;

    转载我的csdn网址:http://download.csdn.net/my

    爬坑的路上要越怕越勇.....
  • 相关阅读:
    Linux文件系统之INode
    手写Netty之多路复用Select小案例
    多路复用器Select、Poll、Epoll区别梳理
    NAT模式、路由模式、桥接模式的区别
    Netty编解码器(理论部分)
    Netty之Unpooled_Bytebuf
    为什么 TCP 协议有粘包问题
    IDEA_2019.1版本中Protobuf的使用
    Netty服务端Server代码说明
    Netty之ChannelHandler
  • 原文地址:https://www.cnblogs.com/shike8080/p/6549339.html
Copyright © 2011-2022 走看看