前段时间公司项目需要跟上一级平台对接一些采集回来的数据,通过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;
}
}
具体哪里的问题,有知道的朋友可以一起讨论,可能我比较笨,第一次弄这个东西,东拼西凑反正能用了,哈哈哈… …