MFC学习之vc通过HTTP请求:Get或Post方式获取JSON信息(亲测可用)

前段时间公司项目需要跟上一级平台对接一些采集回来的数据,通过HTTP,post方法上传JSON信息到指定的接口地址。
本来呢?我在入职时是面试的售后岗,一家小公司,当时公司软件方面一直是外包给其他人代写的,因为涉及到的程序结构不是很复杂,也没有太多新的定制,有初版之后改动不大的情况下,人家都帮忙弄了。
面试的时候,几个领导也简单了解过,知道我懂一些开发的东西,去年也多多少少,帮他们写过一些调试类的小工具。就落下了这个把柄,本来公司没个正经的开发人员,活也不是很多,就又被强制上岗了。

先说下遇到的问题,在网上找了两个相关的类,自己测试之后怎么都不能通信,说实话怎么也不知知道哪里的原因。
一个HTTPTools类和一个WinnetHttp类,需要的大家可以搜“MFC vc通过HTTP请求:Get或Post方式获取JSON信息”,资源已上传,自行下载。
我感觉是可能一个地址解析的时候有问题,但是单步跟过,没有发现什么一样;另一个可能是请求协议头的问题,但是也试了好几个也不行。

这个是WinnetHttp类里的发送和接收部分,大家可以看下或者搜索下载测试。

void CWininetHttp::ConnectAndRecv(const std::string &lpUrl, HttpRequest type, std::string &strHeader, std::string &strPostData)
{
	m_bSucess = true;
	try
	{
		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; 
		DWORD d2=0;
		if ( Hr_Get == type )  
		{  
			bRet = HttpSendRequestA(m_hRequest,strHeader.c_str(),dwHeaderSize,NULL, 0);  
		}  
		else  
		{  
			DWORD dwSize = (strPostData.empty()) ? 0 : strlen(strPostData.c_str());  
			DWORD d1 = GetTickCount();
			bRet = HttpSendRequestA(m_hRequest,strHeader.c_str(),dwHeaderSize,(LPVOID)strPostData.c_str(), dwSize); 
			d2 = GetTickCount()-d1;
		}  
		if ( !bRet )  
		{  
			DWORD n = GetLastError();
			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';  
			m_strRet.append(szBuffer);  
		}
	}
	catch(HttpInterfaceError error)  
	{
		m_strErr = m_mapErr[error];
		m_bSucess = false;
	}
	m_bExit = true;
	std::unique_lock <std::mutex> lck(mtx);
	cv.notify_one();
}

这个是HTTPTools类里的发送和接收部分,大家可以看下或者搜索下载测试。

int HttpTools::HttpRequest(const std::wstring& strMethod,
	const std::wstring& strUrl,
	const std::wstring& postData,
	std::wstring& response,
	const std::wstring& strAgent)
{
	CString strServer;
	CString strObject;
	DWORD dwServiceType;
	INTERNET_PORT nPort;
	response.clear();

	//先解析一下url
	BOOL bParseUrl = AfxParseURL(strUrl.c_str(), dwServiceType, strServer, strObject, nPort);

	if (AFX_INET_SERVICE_HTTP != dwServiceType && AFX_INET_SERVICE_HTTPS != dwServiceType)
	{
		return HTTP_FAILURE;
	}

	CInternetSession *pSession = new CInternetSession(strAgent.c_str());
	CHttpConnection  *pConnection = NULL;
	CHttpFile        *pHttpFile = NULL;

	try
	{
		//创建一个http链接
		pConnection = pSession->GetHttpConnection(strServer,
			dwServiceType == AFX_INET_SERVICE_HTTP ? NORMAL_CONNECT : SECURE_CONNECT,
			nPort);
		//开始一个http请求,映射成HttpFile
		pHttpFile = pConnection->OpenRequest(strMethod.c_str(), strObject,
			NULL, 1, NULL, NULL,(dwServiceType == AFX_INET_SERVICE_HTTP ? NORMAL_REQUEST : SECURE_REQUEST));

		//DWORD dwFlags;
		//m_pFile->QueryOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags);
		//dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
		//set web server option
		//m_pFile->SetOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags);

		pHttpFile->AddRequestHeaders(L"Accept: *,*/*");
		//pHttpFile->AddRequestHeaders(L"Accept-Language: zh-cn");
		//pHttpFile->AddRequestHeaders(L"Content-Type: application/x-www-form-urlencoded;charset=utf-8;");
		//pHttpFile->AddRequestHeaders(L"Accept-Encoding: gzip, deflate");

		pHttpFile->AddRequestHeaders(L"Accept:application/json;");
		pHttpFile->AddRequestHeaders(L"Content-Type:application/json;charset=utf-8;");
		pHttpFile->AddRequestHeaders(L"Content-Type:multipart/form-data;");


		//发送请求 转UTF8
		std::string pData = wstringToUtf8(postData);
		BOOL bResult = pHttpFile->SendRequest(NULL, 0, (LPVOID)pData.data(), (DWORD)postData.length());// *sizeof(char));
		//pHttpFile->SendRequest(NULL, 0, (LPVOID)postData.data(), postData.length() * sizeof(wchar_t));
		if (!bResult)
		{
			return HTTP_FAILURE;
		}

		char szChars[1024] = { 0 };
		std::string strRawResponse;
		UINT nReaded = 0;
		while ((nReaded = pHttpFile->Read((void*)szChars, 1024)) > 0)
		{
			strRawResponse.append(szChars, nReaded);
		}

		/* 把回复结果转为unicode编码,大多数情况下是需要这么做的*/
		int unicodeLen = MultiByteToWideChar(CP_UTF8, 0, strRawResponse.c_str(), -1, NULL, 0);
		WCHAR *pUnicode = new WCHAR[unicodeLen];
		memset(pUnicode, 0, (unicodeLen)*sizeof(wchar_t));

		MultiByteToWideChar(CP_UTF8, 0, strRawResponse.c_str(), -1, pUnicode, unicodeLen);
		std::wstring unicodeRsp;
		unicodeRsp.assign(pUnicode, unicodeLen);
		// 返回值
		response = unicodeRsp;

		delete[]pUnicode;
		pUnicode = NULL;


		if (NULL != pHttpFile)
		{
			pHttpFile->Close();
			delete pHttpFile;
			pHttpFile = NULL;
		}
		if (NULL != pConnection)
		{
			pConnection->Close();
			delete pConnection;
			pConnection = NULL;
		}
		if (NULL != pSession)
		{
			pSession->Close();
			delete pSession;
			pSession = NULL;
		}
	}
	catch (CInternetException* e)
	{
		if (NULL != pHttpFile)
		{
			pHttpFile->Close();
			delete pHttpFile;
			pHttpFile = NULL;
		}
		if (NULL != pConnection)
		{
			pConnection->Close();
			delete pConnection;
			pConnection = NULL;
		}
		if (NULL != pSession)
		{
			pSession->Close();
			delete pSession;
			pSession = NULL;
		}


		DWORD dwErrorCode = e->m_dwError;
		e->Delete();

		DWORD dwError = GetLastError();

		if (ERROR_INTERNET_TIMEOUT == dwErrorCode)
		{
			return HTTP_OUTTIME;
		}
		else
		{
			return HTTP_FAILURE;
		}
	}
	return HTTP_SUCCESS;
}

以上两种方法自己亲测不能用,具体原因不知道,也找了好多其他实例测试过,最后用的也给大家贴在这了,记得收藏哦!!!

bool PostContent(CString strUrl, const CString&strPara, CString &strContent)

{

	try {

		bool bRet = false;

		CString strServer, strObject, strHeader, strRet;

		unsigned short nPort;

		DWORD dwServiceType;

		if (!AfxParseURL(strUrl, dwServiceType, strServer, strObject, nPort))
		{
			return false;
		}

		CInternetSession sess;//Create session

		CHttpFile*pFile;

		CHttpConnection*pServer = sess.GetHttpConnection(strServer, nPort);

		if (pServer == NULL)
		{
			return false;
		}

		pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST, strObject, NULL, 1, NULL, NULL, INTERNET_FLAG_EXISTING_CONNECT);

		if (pFile == NULL)
		{
			return false;
		}

		CString strHeaders = "Content-Type:application/x-www-form-urlencoded;";
		//CString strHeaders = "Accept:application/json;";
		int istrlen = strPara.GetLength();

		pFile->SendRequest(strHeaders, (LPTSTR)(LPCTSTR)strPara, strPara.GetLength());

		//AfxMessageBox((LPTSTR)(LPCTSTR)strPara);

		CString strSentence;
		DWORD dwStatus;
		DWORD dwBuffLen = sizeof(dwStatus);
		BOOL bSuccess = pFile->QueryInfo(HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,&dwStatus, &dwBuffLen);

		if (bSuccess && dwStatus >= 200 && dwStatus<300)
		{
			char buffer[256];
			memset(buffer, 0, 256);
			int nReadCount = 0;
			while ((nReadCount = pFile->Read(buffer, 2048)) > 0)
			{
				strContent += buffer;
				memset(buffer, 0, 256);
			}
			bRet = true;
		}

		else
		{
			bRet = false;
		}

		pFile->Close();
		sess.Close();
		return bRet;
	}

	catch (...)
	{
		int nCode = GetLastError();
		return false;
	}
}

具体哪里的问题,有知道的朋友可以一起讨论,可能我比较笨,第一次弄这个东西,东拼西凑反正能用了,哈哈哈… …

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逃逸的卡路里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值