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);
}
View Code

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);
View Code

 

 

 

转载: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;

 

******************

posted @ 2020-04-11 13:55  htj10  阅读(4442)  评论(0编辑  收藏  举报
TOP