MFC中发送HTTP或HTTPS请求
基本知识
HTTP(超文本传输协议)
HTTPS(超文本传输安全协议)
URL(统一资源定位器)
例子
1. 一个简单的例子
#include <afxinet.h> #include <string> bool testHttp(const CString& strUrl, const BYTE* data, int nBytes, CString& strReceive) { // 解析Url // 例如:https://www.cnblogs.com/Zender/p/7596730.html DWORD dwServiceType; // 协议类型:http/https AFX_INET_SERVICE_HTTP (3) AFX_INET_SERVICE_HTTPS (4107) CString strServer; // Host 例如:www.cnblogs.com 或者 192.168.10.9 CString strObject; // other 例如:/Zender/p/7596730.html INTERNET_PORT wPort; // 端口号 http的默认端口号是80,https的默认端口号是443 if (!AfxParseURL(strUrl, dwServiceType, strServer, strObject, wPort)) { //解析Url失败 return false; } CInternetSession session; // 创建会话 const int nTimeOut = 10 * 1000; // 超时设置为 10s session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, nTimeOut); session.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 2); CHttpConnection* pConn = NULL; CHttpFile* pFile = NULL; if (AFX_INET_SERVICE_HTTP == dwServiceType) { pConn = session.GetHttpConnection(strServer, wPort); pFile = pConn->OpenRequest(CHttpConnection::HTTP_VERB_POST, strObject); } else if (AFX_INET_SERVICE_HTTPS == dwServiceType) { pConn = session.GetHttpConnection(strServer, INTERNET_FLAG_SECURE, wPort); pFile = pConn->OpenRequest(CHttpConnection::HTTP_VERB_POST, strObject, NULL, 1, NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID);//SECURITY_FLAG_IGNORE_UNKNOWN_CA } else { //其他协议返回 return false; } try { CString strHeaders("Content-Type: application/x-www-form-urlencoded");//请求头 BOOL bRet = pFile->SendRequest(strHeaders, (LPVOID)data, nBytes); if (!bRet) { goto Failure_label; } DWORD dwStatusCode; bRet = pFile->QueryInfoStatusCode(dwStatusCode); if (HTTP_STATUS_OK != dwStatusCode)//#define HTTP_STATUS_OK 200 { CString strErrInfo; pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS, strErrInfo); goto Failure_label; } std::string sReceive; char buffer[1024] = { 0 }; for (UINT len = 0; (len = pFile->Read(buffer, sizeof(buffer))) > 0; memset(buffer, 0, sizeof(buffer))) { std::string s(buffer, len); sReceive += s; } strReceive = CStringA(sReceive.c_str(), sReceive.length());//注意:若sReceive中有\0,可能会截断 return true; } catch (CInternetException& e) { TCHAR szErr[512] = { 0 }; e.GetErrorMessage(szErr, sizeof(szErr)); CString strErrInfo; pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS, strErrInfo); goto Failure_label; } Failure_label: if (pConn) { pConn->Close(); delete pConn; pConn = NULL; } if (pFile) { pFile->Close(); delete pFile; pFile = NULL; } return false; } BOOL CtestMFCHttpApp::InitInstance() { CString url("https://www.cnblogs.com/12Zender/p/7596730.html"); CString strReceive; BYTE* data = (BYTE*)"123"; testHttp(url,data,3,strReceive); }
2. 网上别人封装的类(MFC - HTTP(post与get)请求网页内容或图片)
///////////////// CHttpClient.h ////////////// #ifndef HTTPCLIENT_H #define HTTPCLIENT_H #include <afxinet.h> #define IE_AGENT _T("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)") #define REQ_CODE_UTF8 _T("UTF-8") #define REQ_CODE_GBK _T("GBK") // 操作成功 #define SUCCESS 0 // 操作失败 #define FAILURE 1 // 操作超时 #define OUTTIME 2 class CHttpClient { public: CHttpClient(const CString& szReqCode = REQ_CODE_UTF8,LPCTSTR strAgent = IE_AGENT); virtual ~CHttpClient(void); int HttpGet(LPCTSTR strUrl, CString &strResponse); int HttpGetImg(LPCTSTR strUrl, LPCTSTR imgPath); int HttpPost(LPCTSTR strUrl, CString &strResponse, LPCTSTR strPostData); private: int ExecuteRequest(LPCTSTR strMethod, LPCTSTR strUrl, LPCTSTR strPostData, CString &strResponse, LPCTSTR imgPath); void Clear(); CStringA GetReqData(const CString& szReqData); CString GetResData(const CStringA& szResData); private: CInternetSession *m_pSession; CHttpConnection *m_pConnection; CHttpFile *m_pFile; CString m_szReqCode; }; #endif ///////////////////// CHttpClient.cpp /////////////////// ////////////////////////////////// HttpClient.cpp #include "StdAfx.h" #include "HttpClient.h" #define BUFFER_SIZE 1024 #define NORMAL_CONNECT INTERNET_FLAG_KEEP_CONNECTION #define SECURE_CONNECT NORMAL_CONNECT | INTERNET_FLAG_SECURE #define NORMAL_REQUEST INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE #define SECURE_REQUEST NORMAL_REQUEST | INTERNET_FLAG_SECURE | \ INTERNET_FLAG_IGNORE_CERT_CN_INVALID| \ INTERNET_FLAG_IGNORE_CERT_DATE_INVALID CHttpClient::CHttpClient(const CString& szReqCode,LPCTSTR strAgent) { m_pSession = new CInternetSession(strAgent); m_szReqCode = szReqCode; m_pConnection = NULL; m_pFile = NULL; } CHttpClient::~CHttpClient(void) { Clear(); if (NULL != m_pSession) { m_pSession->Close(); delete m_pSession; m_pSession = NULL; } } void CHttpClient::Clear() { if (NULL != m_pFile) { m_pFile->Close(); delete m_pFile; m_pFile = NULL; } if (NULL != m_pConnection) { m_pConnection->Close(); delete m_pConnection; m_pConnection = NULL; } } int CHttpClient::ExecuteRequest(LPCTSTR strMethod, LPCTSTR strUrl, LPCTSTR strPostData, CString &strResponse, LPCTSTR imgPath = NULL) { DWORD dwFlags; CString strServer; CString strObject; DWORD dwServiceType; INTERNET_PORT nPort; strResponse = _T(""); AfxParseURL(strUrl, dwServiceType, strServer, strObject, nPort); if (AFX_INET_SERVICE_HTTP != dwServiceType && AFX_INET_SERVICE_HTTPS != dwServiceType) { return FAILURE; } try { m_pConnection = m_pSession->GetHttpConnection(strServer, dwServiceType == AFX_INET_SERVICE_HTTP ? NORMAL_CONNECT : SECURE_CONNECT,nPort); m_pFile = m_pConnection->OpenRequest(strMethod, strObject, NULL, 1, NULL, NULL, (dwServiceType == AFX_INET_SERVICE_HTTP ? NORMAL_REQUEST : SECURE_REQUEST)); if (AFX_INET_SERVICE_HTTPS == dwServiceType) { m_pFile->QueryOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags); dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA; m_pFile->SetOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags); } m_pFile->AddRequestHeaders(_T("Accept: *,*/*")); m_pFile->AddRequestHeaders(_T("Accept-Language: zh-cn")); m_pFile->AddRequestHeaders(_T("Content-Type: application/x-www-form-urlencoded")); m_pFile->AddRequestHeaders(_T("Accept-Encoding: deflate")); if (strPostData != NULL) { CStringA strData = GetReqData(strPostData); m_pFile->SendRequest(NULL, 0, (LPVOID)(LPCSTR)strData, strlen(strData)); } else { m_pFile->SendRequest(); } char szChars[BUFFER_SIZE + 1] = { 0 }; CStringA strRawResponse = ""; UINT nReaded = 0; if (imgPath == NULL) { while ((nReaded = m_pFile->Read((void*)szChars, BUFFER_SIZE)) > 0) { szChars[nReaded] = '\0'; strRawResponse += szChars; memset(szChars, 0, BUFFER_SIZE + 1); } strResponse = GetResData(strRawResponse); } else { CFile f; f.Open(imgPath, CFile::modeCreate|CFile::modeWrite|CFile::typeBinary); while ((nReaded = m_pFile->Read((void*)szChars, BUFFER_SIZE)) > 0) { szChars[nReaded] = '\0'; f.Write(szChars, BUFFER_SIZE); memset(szChars, 0, BUFFER_SIZE + 1); } f.Close(); } Clear(); } catch (CInternetException* e) { Clear(); DWORD dwErrorCode = e->m_dwError; e->Delete(); DWORD dwError = GetLastError(); if (ERROR_INTERNET_TIMEOUT == dwErrorCode) { return OUTTIME; } else { return FAILURE; } } return SUCCESS; } int CHttpClient::HttpGet(LPCTSTR strUrl, CString &strResponse) { return ExecuteRequest(_T("GET"), strUrl, NULL, strResponse); } int CHttpClient::HttpPost(LPCTSTR strUrl, CString &strResponse, LPCTSTR strPostData) { return ExecuteRequest(_T("POST"), strUrl, strPostData, strResponse); } int CHttpClient::HttpGetImg(LPCTSTR strUrl, LPCTSTR imgPath) { CString str; return ExecuteRequest(_T("GET"), strUrl, NULL, str,imgPath); } CStringA CHttpClient::GetReqData(const CString& szReqData) { // 预算-缓冲区中多字节的长度 int ansiiLen = WideCharToMultiByte(CP_UTF8, 0, szReqData, -1, NULL, 0, NULL, NULL); char * pAssii = (char*)malloc(sizeof(char)*ansiiLen); // 开始向缓冲区转换字节 WideCharToMultiByte(CP_UTF8, 0, szReqData, -1, pAssii, ansiiLen, NULL, NULL); CStringA szRet(pAssii); free(pAssii); return szRet; } CString CHttpClient::GetResData(const CStringA& szResData) { if (m_szReqCode == REQ_CODE_GBK) return CString(szResData); // 预算-缓冲区中宽字节的长度 int unicodeLen = MultiByteToWideChar(CP_UTF8, 0, szResData, -1, NULL, 0); wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen); // 开始向缓冲区转换字节 MultiByteToWideChar(CP_UTF8, 0, szResData, -1, pUnicode, unicodeLen); CString szRet(pUnicode); free(pUnicode); return szRet; } ///////////////////// 使用方法 /////////////////// CHttpClient http; CString url; GetDlgItemText(IDC_EDIT2, url); CString str; http.HttpGet(url, str); AfxMessageBox(str);
转载:https://www.cnblogs.com/Ray-chen/archive/2011/12/14/2287812.html
一、建立会话(Session)对象:
CInternetSession mysession;
二、连接到Http服务器:
CHttpConnection *myconn=mysession.GetHttpConnection("www.baidu.com");
三、打开Http请求:
CHttpFile *myfile=myconn->OpenRequest("GET","/index.html");
四、发送Http请求:
myfile->SendRequest();
五、从服务器读取字节流(bytes):
CString mystr;
CString tmp;
while(myfile->ReadString(tmp))
{
mystr+=tmp;
}六、释放资源:
myfile->Close();
myconn->Close();
mysession.Close();
delete myfile;
delete myconn;
myfile=0;
myconn=0;步骤基本如上,上例各函数参数主要使用默认参数,具体函数声明请查阅MSDN。另外别忘了异常处理!
1、下载文件
Download(const CString& strFileURLInServer, //待下载文件的URL
const CString & strFileLocalFullPath)//存放到本地的路径
{
ASSERT(strFileURLInServer != "");
ASSERT(strFileLocalFullPath != "");
CInternetSession session;
CHttpConnection* pHttpConnection = NULL;
CHttpFile* pHttpFile = NULL;
CString strServer, strObject;
INTERNET_PORT wPort;
DWORD dwType;
const int nTimeOut = 2000;
session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, nTimeOut); //重试之间的等待延时
session.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 1); //重试次数
char* pszBuffer = NULL;
try
{
AfxParseURL(strFileURLInServer, dwType, strServer, strObject, wPort);
pHttpConnection = session.GetHttpConnection(strServer, wPort);
pHttpFile = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject);
if(pHttpFile->SendRequest() == FALSE)
return false;
DWORD dwStateCode;
pHttpFile->QueryInfoStatusCode(dwStateCode);
if(dwStateCode == HTTP_STATUS_OK)
{
HANDLE hFile = CreateFile(strFileLocalFullPath, GENERIC_WRITE,
FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL); //创建本地文件
if(hFile == INVALID_HANDLE_VALUE)
{
pHttpFile->Close();
pHttpConnection->Close();
session.Close();
return false;
}
char szInfoBuffer[1000]; //返回消息
DWORD dwFileSize = 0; //文件长度
DWORD dwInfoBufferSize = sizeof(szInfoBuffer);
BOOL bResult = FALSE;
bResult = pHttpFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH,
(void*)szInfoBuffer,&dwInfoBufferSize,NULL);
dwFileSize = atoi(szInfoBuffer);
const int BUFFER_LENGTH = 1024 * 10;
pszBuffer = new char[BUFFER_LENGTH]; //读取文件的缓冲
DWORD dwWrite, dwTotalWrite;
dwWrite = dwTotalWrite = 0;
UINT nRead = pHttpFile->Read(pszBuffer, BUFFER_LENGTH); //读取服务器上数据
while(nRead > 0)
{
WriteFile(hFile, pszBuffer, nRead, &dwWrite, NULL); //写到本地文件
dwTotalWrite += dwWrite;
nRead = pHttpFile->Read(pszBuffer, BUFFER_LENGTH);
}
delete[]pszBuffer;
pszBuffer = NULL;
CloseHandle(hFile);
}
else
{
delete[]pszBuffer;
pszBuffer = NULL;
if(pHttpFile != NULL)
{
pHttpFile->Close();
delete pHttpFile;
pHttpFile = NULL;
}
if(pHttpConnection != NULL)
{
pHttpConnection->Close();
delete pHttpConnection;
pHttpConnection = NULL;
}
session.Close();
return false;
}
}
catch(...)
{
delete[]pszBuffer;
pszBuffer = NULL;
if(pHttpFile != NULL)
{
pHttpFile->Close();
delete pHttpFile;
pHttpFile = NULL;
}
if(pHttpConnection != NULL)
{
pHttpConnection->Close();
delete pHttpConnection;
pHttpConnection = NULL;
}
session.Close();
return false;
}
if(pHttpFile != NULL)
pHttpFile->Close();
if(pHttpConnection != NULL)
pHttpConnection->Close();
session.Close();
return true;
}
2、上传文件
bool Download(const CString& strFileURLInServer, //待下载文件的URL
const CString & strFileLocalFullPath)//存放到本地的路径
{
ASSERT(strFileURLInServer != "");
ASSERT(strFileLocalFullPath != "");
CInternetSession session;
CHttpConnection* pHttpConnection = NULL;
CHttpFile* pHttpFile = NULL;
CString strServer, strObject;
INTERNET_PORT wPort;
bool bReturn = false;
DWORD dwType;
const int nTimeOut = 2000;
session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, nTimeOut); //重试之间的等待延时
session.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 1); //重试次数
char* pszBuffer = NULL;
try
{
AfxParseURL(strFileURLInServer, dwType, strServer, strObject, wPort);
pHttpConnection = session.GetHttpConnection(strServer, wPort);
pHttpFile = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject);
if(pHttpFile->SendRequest() == FALSE)
return false;
DWORD dwStateCode;
pHttpFile->QueryInfoStatusCode(dwStateCode);
if(dwStateCode == HTTP_STATUS_OK)
{
HANDLE hFile = CreateFile(strFileLocalFullPath, GENERIC_WRITE,
FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL); //创建本地文件
if(hFile == INVALID_HANDLE_VALUE)
{
pHttpFile->Close();
pHttpConnection->Close();
session.Close();
return false;
}
char szInfoBuffer[1000]; //返回消息
DWORD dwFileSize = 0; //文件长度
DWORD dwInfoBufferSize = sizeof(szInfoBuffer);
BOOL bResult = FALSE;
bResult = pHttpFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH,
(void*)szInfoBuffer,&dwInfoBufferSize,NULL);
dwFileSize = atoi(szInfoBuffer);
const int BUFFER_LENGTH = 1024 * 10;
pszBuffer = new char[BUFFER_LENGTH]; //读取文件的缓冲
DWORD dwWrite, dwTotalWrite;
dwWrite = dwTotalWrite = 0;
UINT nRead = pHttpFile->Read(pszBuffer, BUFFER_LENGTH); //读取服务器上数据
while(nRead > 0)
{
WriteFile(hFile, pszBuffer, nRead, &dwWrite, NULL); //写到本地文件
dwTotalWrite += dwWrite;
nRead = pHttpFile->Read(pszBuffer, BUFFER_LENGTH);
}
delete[]pszBuffer;
pszBuffer = NULL;
CloseHandle(hFile);
bReturn = true;
}
}
catch(CInternetException* e)
{
TCHAR tszErrString[256];
e->GetErrorMessage(tszErrString, ArraySize(tszErrString));
TRACE(_T("Download XSL error! URL: %s,Error: %s"), strFileURLInServer, tszErrString);
e->Delete();
}
catch(...)
{
}
if(pszBuffer != NULL)
{
delete[]pszBuffer;
}
if(pHttpFile != NULL)
{
pHttpFile->Close();
delete pHttpFile;
}
if(pHttpConnection != NULL)
{
pHttpConnection->Close();
delete pHttpConnection;
}
session.Close();
return bReturn;
}
******************
常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。
昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否?知否?应是绿肥红瘦。