添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

笔者这里有需求, 需要用C++实现 https 的GET、POST请求 以及GET下载文件 而且需要实现跨平台 在Linux、Windows都能正常运行 。最好的是 只用一套代码 而不是根据具不同平台 跑不同代码,所以我们得找一个跨平台的支持https协议的库。都不用想, 最好的当然是 OpenSSL啦 。也有其他的比如libcurl 啥的,但是libcurl如果要支持https的也要链接OpenSSL了,还不如直接用OpenSSL。 当然这里还有个不错的选择就是使用boost::asio库 ,但是笔者觉得使用上没有OpenSSL好用,故此没有用boost库。

网上示例代码比较多,笔者这里也是简单写了小demo,在Windows平台和Linux平台都能正常运行,只是为在互联网上多一个链接,让需要者多一篇可参考的博客而已。 这里使用的是openssl-1.0.2m 版本,OpenSSL更高的版本没有测试,想来 api改动应该不大。

MyHttpsUtil.h

#pragma once
#include <string>
#include <openssl/ssl.h>
enum REQ_TYPE
    GET_STRING = 0, // GET请求获取响应字符串
    POST_STRING,    // POST请求获得响应字符串
    GET_FILE        // GET请求下载文件
class MyHttpsUtil
    public:
    virtual ~MyHttpsUtil(void);
    static MyHttpsUtil* getInstance();
        https get请求
        return value
            0:成功 strResponse为响应结果 -1:失败,strResponse为错误信息
    int getRequest(const std::string& strSvrIp, int iSvrPort, 
        const std::string& strUri, std::string& strResponse);
        https post请求
        return value
            0:成功 strResponse为响应结果 -1:失败,strResponse为错误信息
    int postRequest(const std::string& strSvrIp, int iSvrPort, 
        const std::string& strUri, const std::string& strBody, std::string& strResponse);
        https get请求下载文件
        return value
            0:成功 -1:失败,strErrMsg为错误信息
    int getFile(const std::string& strSvrIp, int iSvrPort, 
        const std::string& strUri, const std::string& strBody, const std::string& strFilePath, std::string& strErrMsg );
private:
    MyHttpsUtil(void);
private:
    // 建立TCP连接套接字
    int tcpConn(const char* pSvrIp, int iSvrPort, int& socket);
        发送数据到https服务器
        参数1:请求类型,决定最后3个参数的作用
        参数2:服务器IP
        参数3:服务器端口
        参数4:uri
        参数5:reqType:1 为POST_STRING时(POST请求) 请求参数,也就是请求体。
        参数6:reqType:2 为GET_FILE时(GET请求下载资源文件) 文件存储路径。
        参数7:reqType:0/1 为GET_STRING/POST_STRING 时(GET/POST请求响应字符串) 响应字符串在strResponse, 出现错误时 错误描述信息在strResponse中。
    int sendDataToSvr(REQ_TYPE reqType, const std::string& strSvrIp, int iSvrPort, 
        const std::string& strUri, const std::string& strBody, const std::string& strFilePath, std::string& strResponse );
    // 组装GET请求数据
    int getGetReqData(const std::string& strSvrIp, int iSvrPort, 
        const std::string& strUri, std::string& strReqData);
    // 组装POST请求数据
    int getPostReqData(const std::string& strSvrIp, int iSvrPort, 
        const std::string& strUri, const std::string& strBody, std::string& strReqData);
    // 读取响应字符串
    int readResponseToString(SSL* ssl, std::string& strRespData);
    // 读取响应二进制数据到文件
    int readResponseToFile(SSL* ssl, const std::string& strFilePath, std::string& strErrMsg);

MyHttpsUtil.cpp

#include "MyHttpsUtil.h"
#ifdef WIN32
#include <winsock.h>
#else
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#endif
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/crypto.h>
#define CODE_SUCCESS 0
#define CODE_FALID -1
#ifdef WIN32
#pragma comment(lib, "libeay32.lib")
#pragma comment(lib, "ssleay32.lib")
#endif
MyHttpsUtil::MyHttpsUtil(void)
MyHttpsUtil::~MyHttpsUtil(void)
MyHttpsUtil* MyHttpsUtil::getInstance()
    static MyHttpsUtil httpsClient;
    return &httpsClient;
int MyHttpsUtil::getRequest(const std::string& strSvrIp, int iSvrPort, 
    const std::string& strUri, std::string& strResponse)
    return sendDataToSvr(GET_STRING, strSvrIp, iSvrPort, strUri, "", "", strResponse);
int MyHttpsUtil::postRequest(const std::string& strSvrIp, int iSvrPort, 
    const std::string& strUri, const std::string& strBody, std::string& strResponse)
    return sendDataToSvr(POST_STRING, strSvrIp, iSvrPort, strUri, strBody, "", strResponse);
int MyHttpsUtil::getFile(const std::string& strSvrIp, int iSvrPort, 
    const std::string& strUri, const std::string& strBody, const std::string& strFilePath, std::string& strErrMsg)
    return sendDataToSvr(GET_FILE, strSvrIp, iSvrPort, strUri, "", strFilePath, strErrMsg);
int MyHttpsUtil::sendDataToSvr(REQ_TYPE reqType, const std::string& strSvrIp, int iSvrPort, const std::string& strUri, const std::string& strBody, const std::string& strFilePath, std::string& strResponse)
    int iRet = CODE_FALID;
    int socketFd = 0;
    SSL_CTX* ctx = 0;
    SSL* ssl = 0;
        char* pSvrIp = NULL;
        struct hostent *pHostent = NULL;
        pHostent = gethostbyname(strSvrIp.c_str());
        if (pHostent == NULL)
            break;
        pSvrIp = inet_ntoa(*(struct in_addr*)pHostent->h_addr_list[0]);
        // 1.建立TCP连接
        if( tcpConn(pSvrIp, iSvrPort, socketFd) != CODE_SUCCESS)
            break;
        // 2.SSL初始化, 关联Socket到SSL,并建立连接
        SSL_library_init();
	    OpenSSL_add_all_algorithms();
	    SSL_load_error_strings(); 
	    ctx = SSL_CTX_new(SSLv23_client_method()); 
        if(ctx == NULL)
            break;
	    ssl = SSL_new(ctx);
        SSL_set_fd(ssl, socketFd);
        int retCode = SSL_connect(ssl);
        if ( retCode != 1)
            int sslErrCode = SSL_get_error(ssl,retCode);
            strResponse = "SSL_connect error,openssl errCode = ";
            char errCode[11] = {0};
            sprintf_s(errCode, "%d", sslErrCode);
            strResponse.append(errCode);
            break;
        std::string strReqData;
        if(GET_FILE == reqType || GET_STRING == reqType)
            getGetReqData(strSvrIp, iSvrPort, strUri, strReqData);
            getPostReqData(strSvrIp, iSvrPort, strUri, strBody, strReqData);
	    // 4.通过SSL发送数据,数据量不大一次write就够了,如果是文件上传就需要循环写了。
	    int writeLen = SSL_write(ssl, strReqData.c_str(), strReqData.length());  
	    if (writeLen <=0)
		    int sslErrCode = SSL_get_error(ssl,writeLen);
            strResponse = "SSL_write error,openssl errCode = ";
            char errCode[11] = {0};
            sprintf_s(errCode, "%d", sslErrCode);
            strResponse.append(errCode);
            break;
	    // 5.读取响应数据  
        int readLen = 0;
        char pHeader[1] = {0};
        int i = 0;
	    // 响应头以\r\n\r\n 结束, 此处判断头是否传输完成
	    while((readLen = SSL_read(ssl, pHeader, 1)) == 1)
		    if(i < 4){
			    if(pHeader[0] == '\r' || pHeader[0] == '\n')
				    if(i >= 4)
					    break;
				    i = 0;
        if( readLen < 0 )
            int sslErrCode = SSL_get_error(ssl,readLen);
            strResponse = "SSL_read error,openssl errCode = ";
            char errCode[11] = {0};
            sprintf_s(errCode, "%d", sslErrCode);
            strResponse.append(errCode);
            break;
        if(GET_FILE == reqType)
            iRet = readResponseToFile(ssl, strFilePath, strResponse);
            iRet = readResponseToString(ssl, strResponse);
    } while (false);
    // 6.关闭socket、断开连接
    if (socket)
#ifdef WIN32
        closesocket(socketFd);
#else
        close(socketFd);
#endif
    if (ctx)
        SSL_CTX_free(ctx);
    if (ssl)
        SSL_shutdown (ssl);
        SSL_free(ssl);
    return iRet;
int MyHttpsUtil::tcpConn(const char* pSvrIp, int iSvrPort, int& socket)
    socket = ::socket(AF_INET,SOCK_STREAM,0);
    if( socket == -1 )
        return CODE_FALID;
    sockaddr_in sa;
    sa.sin_addr.s_addr = inet_addr(pSvrIp);
    sa.sin_port = htons(iSvrPort);
    sa.sin_family = AF_INET;
    int retCode = ::connect(socket,(struct sockaddr*)&sa,sizeof(sa));  
    if(retCode == -1)  
        return CODE_FALID;
    return CODE_SUCCESS;
int MyHttpsUtil::getGetReqData(const std::string& strSvrIp, int iSvrPort, 
    const std::string& strUri, std::string& strReqData)
    char pLine[256] = {0};
	sprintf_s(pLine, "GET %s HTTP/1.1\r\n", strUri.c_str());
    strReqData.append(pLine);
    memset(pLine, 0, sizeof(pLine));
	sprintf_s(pLine, "Host: %s:%d\r\n",strSvrIp.c_str(), iSvrPort);
    strReqData.append(pLine);
    memset(pLine, 0, sizeof(pLine));
    strReqData.append("Accept: */*\r\n");
    strReqData.append("Connection: close\r\n\r\n");
    //strReqData.append("Connection: keep-alive\r\n\r\n");
    return CODE_SUCCESS;
int MyHttpsUtil::getPostReqData(const std::string& strSvrIp, int iSvrPort, 
    const std::string& strUri, const std::string& strBody, std::string& strReqData)
    char pLine[256] = {0};
	sprintf_s(pLine, "POST %s HTTP/1.1\r\n", strUri.c_str());
    strReqData.append(pLine);
    memset(pLine, 0, sizeof(pLine));
	sprintf_s(pLine, "Host: %s:%d\r\n",strSvrIp.c_str(), iSvrPort);
    strReqData.append(pLine);
    memset(pLine, 0, sizeof(pLine));
    strReqData.append("Accept: */*\r\n");
    strReqData.append("Content-Type: application/json; charset=utf-8\r\n");
    memset(pLine, 0, sizeof(pLine));
    sprintf_s(pLine, "Content-Length: %d\r\n", strBody.length());
    strReqData.append("Connection: close\r\n\r\n");
    strReqData.append(strBody);
    return CODE_SUCCESS;
int MyHttpsUtil::readResponseToString(SSL* ssl, std::string& strRespData)
    // 读取响应体数据,一次读1k
    char pBody[1024 + 1] = {0};
    int readSize = sizeof(pBody) -1;
    int readLen = 0;
    while( (readLen = SSL_read(ssl, pBody, readSize)) > 0 )
        strRespData.append(pBody);
        memset(pBody, 0, sizeof(pBody));
    if(readLen < 0)
        int sslErrCode = SSL_get_error(ssl,readLen);
        strRespData = "SSL_read error,openssl errCode = ";
        char errCode[11] = {0};
        sprintf_s(errCode, "%d", sslErrCode);
        strRespData.append(errCode);
        return CODE_FALID;
    strRespData.append(pBody);
    return CODE_SUCCESS;
int MyHttpsUtil::readResponseToFile(SSL* ssl, const std::string& strFilePath, std::string& strErrMsg)
    FILE *fp = fopen(strFilePath.c_str(), "wb+");
    if(fp == NULL)
        strErrMsg = "fopen error,filePath:";
        strErrMsg.append(strFilePath);
        return CODE_FALID;
    char pBody[1024 + 1] = {0};
    int readSize = sizeof(pBody) -1;
    int readLen = 0;
    while( (readLen = SSL_read(ssl, pBody, readSize)) > 0 )
        if( fwrite(pBody, 1, readLen, fp) != readLen)
            strErrMsg = "fwrite error";
            return CODE_FALID;
        memset(pBody, 0, sizeof(pBody));
    if(readLen < 0)
        int sslErrCode = SSL_get_error(ssl,readLen);
        strErrMsg = "SSL_read error,openssl errCode = ";
        char errCode[11] = {0};
        sprintf_s(errCode, "%d", sslErrCode);
        strErrMsg.append(errCode);
        return CODE_FALID;
    if( fwrite(pBody, 1, readLen, fp) != readLen)
        strErrMsg = "fwrite error";
        return CODE_FALID;
    fclose(fp);
    return CODE_SUCCESS;

这里我们以 https://www.baidu.com 进行测试 GET、POST、GET下载文件,接口均正常。

test.cpp

#include "MyHttpsUtil.h"
#include <iostream>
int main(int argc, char* argv[])
    std::string strResponse;
    if( MyHttpsUtil::getInstance()->getRequest("www.baidu.com", 443, "/", strResponse) == 0)
        //std::cout << strResponse << std::endl; // 太长了,下个输出无法输出
        std::cout << "get req suc" << std::endl;
         std::cout << "get req error" << std::endl;
    std::cout << "=======================" << std::endl;
    strResponse.clear();
    if( MyHttpsUtil::getInstance()->postRequest("www.baidu.com", 443, "/", "{}", strResponse) == 0)
         std::cout << "post req suc" << std::endl;
         std::cout << strResponse << std::endl;
        std::cout << "post req error" << std::endl;
    std::cout << "=======================" << std::endl;
    std::string strErrMsg;
    if( MyHttpsUtil::getInstance()->getFile("www.baidu.com", 443, "/", strResponse,"c:\\1.txt", strErrMsg) == 0 )
        std::cout << "get req downlaod file suc" << std::endl;
        std::cout << "get req downlaod file error:" << strErrMsg << std::endl;
    std::cout << "=======================" << std::endl;
    getchar();
    return 0;
                    前言笔者这里有需求,需要用C++实现 https 的GET、POST请求 以及GET下载文件 而且需要实现跨平台 在Linux、Windows都能正常运行。最好的是 只用一套代码 而不是根据具不同平台 跑不同代码,所以我们得找一个跨平台的支持https协议的库。都不用想,最好的当然是 OpenSSL啦。也有其他的比如libcurl 啥的,但是libcurl如果要支持https的也要链接OpenSSL了,还不如直接用OpenSSL。当然这里还有个不错的选择就是使用boost::asio库,但是笔者觉得使用上
				
本代码使用MFC方式实现了如下功能: 1> 原生socket POST访问HTTP站点。可成功登陆某站点; 2> 集成OpenSSL POST访问HTTPS站点。可成功登陆小米官网。 文件包内含有完整的,编译好的OpenSSL开发需要的头文件以及库文件等,可以方便的使用在您的项目中。
HTTPS中SSL的通信具体过程1、https中SSL通讯的前置准备工作2、openssl库相关函数介绍2.1、重要参数讲解3、SSL框架图4、demo4.1、sslserver.c4.2、sslclient.c 1、https中SSL通讯的前置准备工作 https通信需要用到openssl库。 openssl库安装: sudo apt-get install openssl https中ssl通信还需要用到证书,私钥,公钥等信息,详情请查看: 如何自建根证书 如何建立中继 如何建立服务器证书 import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; * 证书信任管理器(用于https请求) * 这个证书管
文章参考:https://blog.csdn.net/u014049599/article/details/79998674 一、编写“HttpRequest.h”文件 #pragma once #include <string> #include <vector> #include<map> #include <curl/curl.h> cla...
通过之前对的lic流程我们可以用get去抓取http协议上的内容,但是面对人脸识别中的https协议却没有办法,连接不上,错误代码总显示3。 原因是我们没有安装openSSLhttps=http+SSL。 安装openSSL流程 1.1、下载openssl源码 wget https://ftp.openssl.org/source/old/1.1.1/openssl-1.1.1i.tar.gz 1.2、解压、配置、编译并安装 1.tar -xzf openssl-1.1.1i.tar.gz 2.cd o
        由于项目升级,在数据传输过程中需要经过OAuth2.0认证,访问服务器需要https协议。         首先,实现C++代码访问https 服务器,实现Get和post功能,在网上搜索一通,发现各种各样的都有,有的很简单,有的稍微复杂。结果MSDN介绍的比较简洁一点         官方网址:https://docs.microsoft.com/en-us/windows/...
C++ 实现 HTTP HTTPS POST GET(包含curl版本和winhttp两种实现)。 玩过抓包,网络协议分析的朋友肯定都知道http https post get,web端和用户的交互主要是通过post get完成的。 我这里有两种实现: 1:libcurl实现的CHttpClient类,该类实现了Htpp和Https的get post方法。 2:winhttp实现的WinHttpClient类,同样也实现了Htpp和Https的get post方法。 两者使用起来都很方便灵活。 详细说明: http://blog.csdn.net/sunflover454/article/details/49030803 HTTP HTTPS POST GET winhttp
fatal: unable to access 'https://github.com/adobe-webplatform/eve.git/': openssl ssl_read: connection was reset, errno 10054
### 回答1: 这是一个错误信息,意思是无法访问 https://github.com/adobe-webplatform/eve.git/,可能是由于 SSL 连接被重置导致的。errno 10054 是一个网络错误代码,表示连接被远程主机重置。可能是网络问题或者服务器问题导致的。建议稍后再尝试访问,或者检查网络连接和服务器状态。 ### 回答2: 这个错误提示是由于使用HTTPS协议连接到GitHub时,SSL连接出现异常而导致连接被重置。这种情况很可能是因为你的电脑和GitHub服务器之间的加密协议不兼容或者网络连接不稳定所致。 解决办法可以尝试以下几种: 1. 检查网络连接是否稳定,是否存在断网等问题,并重新连接。 2. 更新git版本,使用最新版本的git可以避免一些因为旧版本协议不兼容引起的问题。 3. 检查电脑系统和软件的SSL证书是否存在问题,可能是系统或软件中的证书过期或异常,可以尝试重新安装或更新证书。 4. 可以尝试换用其他协议连接GitHub,如SSH等。 5. 如果以上方法均无效,可以尝试先将代码克隆到本地再进行操作,或者联系GitHub客服解决问题。 总之,如遇到这个错误提示,需要先检查网络连接和软件版本等基础问题,再逐渐排查具体原因,并采取相应的解决方法。 ### 回答3: 这个错误信息是说无法访问GitHub上的某个项目,具体错误原因是OpenSSL在进行SSL传输时连接被重置了。错误代码10054表示操作已被对端强制关闭,例如连接超时或服务器关闭了连接等。 要解决这个问题,有几个可能的原因和解决方法: 1. 网络连接问题:网络连接不稳定或防火墙设置导致无法连接到GitHub服务器。我们可以尝试重启电脑或路由器,或者暂时关闭防火墙,看能否解决问题。 2. 代理设置问题:如果我们使用了代理服务器访问GitHub,可能会导致出现这个错误。我们需要检查代理服务器的设置是否正确,或者尝试更换其他代理服务器。 3. SSL证书问题:可能是因为SSL证书不匹配或配置错误导致无法进行SSL传输。我们可以尝试更新证书或者重新配置SSL设置。 4. 版本控制工具问题:也有可能是因为Git客户端版本过低或配置错误导致无法连接到GitHub服务器。我们可以尝试升级Git客户端或者重新配置Git设置。 总之,这个错误信息的原因可能有很多,需要根据具体情况逐个排查。如果尝试了上述方法仍无法解决问题,建议咨询GitHub官方技术支持或者搜索相关技术论坛寻求帮助。
CSDN-Ada助手: 嗨~好久未见你更新博文了,我们现在上线了AI创作助手哦~可为你的创作提供智能化帮助,快来试试吧~https://editor.csdn.net/md/?not_checkout=1&utmsource=blog_comment_recall,在编辑器页面右侧哦~~限免!! 同时我们为您准备了一份回归奖励,快来看看吧https://activity.csdn.net/creatActivity?id=10430&utmsource=blog_comment_recall Windows编程—获取操作系统默认浏览器路径 Firststyledo: xp下不行,没有注册表项 树:二叉树的内存拷贝和内存释放 danzouyizhangliu: 释放二叉树的时候参数要不要以&tree的形式传入 COM原理与应用(潘爱民)带目录书签下载 weixin_44911930: 谢谢,非常好