Windows下C++调用Http接口
1、WininetHttp.h
#pragma once
#include
#include
#include
#include
#include
using namespace std;//每次读取的字节数
#define READ_BUFFER_SIZE 4096enum HttpInterfaceError
{Hir_Success = 0, //成功Hir_InitErr, //初始化失败Hir_ConnectErr, //连接HTTP服务器失败Hir_SendErr, //发送请求失败Hir_QueryErr, //查询HTTP请求头失败Hir_404, //页面不存在Hir_IllegalUrl, //无效的URLHir_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://单例模式static CWininetHttp& getInstance(){static CWininetHttp m_winHttp;return m_winHttp;}CWininetHttp(const CWininetHttp &) = delete;CWininetHttp& operator =(const CWininetHttp &) = delete;~CWininetHttp(void);//同步获取http请求string synRequestInfo(const string& lpUrl, HttpRequest type, map<string, string> param = map<string, string>());//异步获取http请求void asynRequestInfo(const string& lpUrl, HttpRequest type, map<string, string> param, std::function<void(string)> callBack);
private:CWininetHttp(void);// 通过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 = "");string getUrl(const string& lpUrl, map<string, string> param);void asynRequestThread(string totalUrl, HttpRequest type);// 关闭句柄 void Release();// 释放句柄void ReleaseHandle(HINTERNET& hInternet);// 解析URL地址 void ParseURLWeb(std::string strUrl, std::string& strHostName, std::string& strPageName, WORD& sPort);// UTF-8转为GBK2312char* UtfToGbk(const char* utf8);private:HINTERNET m_hSession;HINTERNET m_hConnect;HINTERNET m_hRequest;HttpInterfaceError m_error;std::function<void(string)> callBack = NULL;
};
WininetHttp.cpp
#include "stdafx.h"
#include "WininetHttp.h"
#include
#pragma comment(lib, "Wininet.lib")
#include
#include
CWininetHttp::CWininetHttp(void) :m_hSession(NULL), m_hConnect(NULL), m_hRequest(NULL)
{
}CWininetHttp::~CWininetHttp(void)
{Release();
}//同步请求
string CWininetHttp::synRequestInfo(const string& lpUrl, HttpRequest type,map<string,string> param)
{string totalUrl = getUrl(lpUrl, param);return RequestJsonInfo(totalUrl, type);
}//异步请求线程
void CWininetHttp::asynRequestThread(string totalUrl, HttpRequest type)
{string jsonStr = RequestJsonInfo(totalUrl, type);if(callBack != NULL)callBack(jsonStr);
}//异步请求
void CWininetHttp::asynRequestInfo(const string& lpUrl, HttpRequest type, map<string, string> param, std::function<void(string)> callBack)
{this->callBack = callBack;string totalUrl = getUrl(lpUrl, param);thread t(&CWininetHttp::asynRequestThread,this, totalUrl, type);t.detach();
}//拼接地址
string CWininetHttp::getUrl(const string& lpUrl, map<string, string> param) {string paramstr = "";string totalUrl = lpUrl;for (map<string, string>::iterator ite = param.begin(); ite != param.end(); ite++){paramstr += ite->first + "=" + ite->second + "&";}if (paramstr.length() > 0){paramstr = paramstr.substr(0, paramstr.length() - 1);totalUrl = lpUrl + "?" + paramstr;}return totalUrl;
}/*
lpUrl:url地址,如 http://127.0.0.1:8081/hello?name=csy ,其中?后为参数
type:请求类型 get or post
strHeader:可增添头部,一般为空
strPostData:post请求参数,但是这里好像不生效,可统一将参数拼接到lpUrl中
*/
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,\nstrHostName:%s,\nstrPageName:%s,\nport:%d\n", 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] = '\0';strRet.append(szBuffer);}}catch (HttpInterfaceError error){m_error = error;}strRet = UtfToGbk(strRet.c_str());return strRet;
}// 解析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);
}void CWininetHttp::Release()
{ReleaseHandle(m_hRequest);ReleaseHandle(m_hConnect);ReleaseHandle(m_hSession);
}void CWininetHttp::ReleaseHandle(HINTERNET& hInternet)
{if (hInternet){InternetCloseHandle(hInternet);hInternet = NULL;}
}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;
}
3、main.cpp
#include "WininetHttp.h"
#include
#include
#include "json/json.h"
#include int main()
{map<string, string> param;param.insert(pair<string, string>("sbId", "98"));//1、同步调用string jsonStr = CWininetHttp::getInstance().synRequestInfo("http://114.115.151.44:12011/base/dictSbsx/v1/list", Hr_Get, param);std::cout << jsonStr << std::endl;//2、异步调用CWininetHttp::getInstance().asynRequestInfo("http://114.115.151.44:12011/base/dictSbsx/v1/list", Hr_Get, param, [=](string jsonStr){std::cout << jsonStr << std::endl;});getchar();return 0;
}
其中json请引入json库
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
