1.此处将openssl的初始化封装为了单例类,仅在程序启动时调用一次
api.h
#ifndef STREAM_MANAGER_H
#define STREAM_MANAGER_H
#include "https_client.h"
class API
{
public:
API();
~API();
void GetRecordPath();
public:
HttpsClient* m_hClient;
char* m_response;
bool m_flag;
size_t m_resp_allsize;
private:
std::string m_record_path;
double m_diskThreshold;
};
#endif
api.cpp
#include "api.h"
#include "json/json.h"
#include <unistd.h>
#include <sys/time.h>
#include "https_client.h"
#include <event2/buffer.h>
API::API()
{
m_hClient = new HttpsClient;
m_hClient->Init();
m_record_path = "";
m_diskThreshold = 0;
m_response =new char[8092];
memset(m_response,0,sizeof(m_response));
m_flag = false;
m_resp_allsize = 8092;
}
API::~API()
{
if (m_hClient)
{
delete m_hClient;
}
if (m_response != NULL)
{
delete []m_response;
}
}
static void HttpsClientCbFunc(struct evhttp_request* req, void* arg) {
API* self = static_cast<API*>(arg);
event_base* base = (event_base *)(self->m_hClient->m_base);
if (req == NULL || evhttp_request_get_response_code(req) != 200)
{
std::cout << "请求失败"<< evhttp_request_get_response_code(req)<<std::endl;
self->m_flag = true;
return ;
}
std::cout << evhttp_request_get_response_code(req)<<std::endl;
evbuffer* input = evhttp_request_get_input_buffer(req);
memset(self->m_response,0,self->m_resp_allsize);
size_t allsize = 8092;
size_t cursize = 0;
char buf[1024] = { 0 };
for (;;)
{
int len = evbuffer_remove(input, buf, sizeof(buf));
if (len <= 0)break;
if (len + cursize > allsize)
{
char* pNewResponse = new char[allsize * 2]; // 新分配的内存大小为原来的两倍
memcpy(pNewResponse, self->m_response, cursize); // 将原来的数据拷贝到新内存中
delete[] self->m_response; // 释放原来的内存
self->m_response = pNewResponse;
allsize *= 2;
}
memcpy(&self->m_response[cursize], buf, len); // 拷贝len长度的数据到m_response中
// 将m_response的位置向后移动len个字节
cursize += len;
std::cout << "Received data: " << buf << std::endl;
}
self->m_resp_allsize = allsize;
self->m_flag = true;
event_base_loopbreak(base);
}
void API::GetRecordPath()
{
m_hClient->PostHttpsClient("158.100.6.14",10999,"/login","",HttpsClientCbFunc,this);
while(true)
{
if (m_flag)
{
break;
}
else
{
usleep(40000);
}
}
m_flag = false;
printf("resp---------%s------",m_response);
memset(m_response,0,sizeof(m_response));
return;
}
https_client.cpp
#include <openssl/ssl.h>
#include <event2/bufferevent_ssl.h>
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/http.h>
#include "OpensslInit.h"
#include "https_client.h"
HttpsClient::HttpsClient(){
}
int HttpsClient::Init()
{
auto ctx = SingletonOpensslInit::getInstance().GetCtx();
m_base = event_base_new();
if (!m_base) {
printf("Failed to create event_base.");
return -1;
}
SSL* ssl = SSL_new(ctx);
m_bev = bufferevent_openssl_socket_new(m_base, -1, ssl,
BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_CLOSE_ON_FREE);
if (!m_bev) {
printf("Failed to create bufferevent.");
return -2;
}
return 0;
}
HttpsClient::~HttpsClient()
{
if (m_base != NULL)
{
event_base_free(m_base);
}
}
int HttpsClient::GetHttpsClient(const char* host,const int port,const char* path, HttpsClientCb callback, void* arg)
{
if (bufferevent_socket_connect_hostname(m_bev, nullptr, AF_UNSPEC, host, port) < 0) {
printf("Failed to connect to HTTPS server.");
return -7;
}
evhttp_request* httpreq = evhttp_request_new(callback, arg);
if (!httpreq) {
printf("Failed to create evhttp_request.");
return -1;
}
evhttp_add_header(evhttp_request_get_output_headers(httpreq),
"Host", host);
evhttp_make_request(evhttp_connection_base_bufferevent_new(m_base, NULL, m_bev, host, port),
httpreq, EVHTTP_REQ_GET, path);
event_base_dispatch(m_base);
return 0;
}
int HttpsClient::PostHttpsClient(const char* host,const int port,const char* path,const char* body, HttpsClientCb callback, void* arg) {
if (bufferevent_socket_connect_hostname(m_bev, NULL, AF_UNSPEC, host, port) < 0) {
printf("Failed to connect to HTTPS server.");
return -8;
}
evhttp_request* req = evhttp_request_new(callback, arg);
evkeyvalq* output_header = evhttp_request_get_output_headers(req);
evhttp_add_header(output_header, "Host", host);
evhttp_add_header(output_header, "Content-Type", "application/json");
//发送post数据
evbuffer* output = evhttp_request_get_output_buffer(req);
size_t len = strlen(body);
evbuffer_add(output, body, len);
//发起请求
evhttp_make_request(evhttp_connection_base_bufferevent_new(m_base, NULL, m_bev, host, port), req, EVHTTP_REQ_POST, path);
event_base_dispatch(m_base);
return 0;
}
https_client.cpp
#ifndef HTTPS_CLIENT_H
#define HTTPS_CLIENT_H
#include <iostream>
#include <openssl/ssl.h>
#include <event2/event.h>
#include <event2/bufferevent_ssl.h>
#include <event2/http.h>
typedef void (*HttpsClientCb)(evhttp_request*, void*);
class HttpsClient {
public:
HttpsClient();
~HttpsClient();
int GetHttpsClient(const char* host,const int port,const char* path, HttpsClientCb callback, void* arg);
int PostHttpsClient(const char* host,const int port,const char* path,const char* body, HttpsClientCb callback, void* arg);
int Init();
char* m_response;
event_base* m_base;
bool* m_flag;
private:
SSL_CTX* m_ctx;
bufferevent* m_bev;
};
#endif
OpenInit.h
#pragma once
#ifndef OPENSSL_INIT_H
#define OPENSSL_INIT_H
#include <openssl/ssl.h>
#include <event2/bufferevent_ssl.h>
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/http.h>
#include <iostream>
class SingletonOpensslInit {
public:
static SingletonOpensslInit& getInstance();
int Init();
SSL_CTX* GetCtx();
private:
SingletonOpensslInit() {}
~SingletonOpensslInit();
SingletonOpensslInit(const SingletonOpensslInit&) = delete;
SingletonOpensslInit& operator=(const SingletonOpensslInit&) = delete;
// event_base* m_base;
SSL_CTX* m_ctx;
// bufferevent* m_bev;
};
#endif
OpenInit.cpp
#include "OpensslInit.h"
#define HTTP_CERT_PEM "cert.pem"
#define HTTP_KEY_PEM "key.pem"
SingletonOpensslInit& SingletonOpensslInit::getInstance() {
static SingletonOpensslInit instance;
return instance;
}
SingletonOpensslInit::~SingletonOpensslInit()
{
if (m_ctx != NULL)
{
SSL_CTX_free(m_ctx);
}
}
int SingletonOpensslInit::Init()
{
SSL_load_error_strings ();
SSL_library_init();
OpenSSL_add_all_algorithms ();
m_ctx = SSL_CTX_new(SSLv23_client_method ());
if (!m_ctx) {
std::cerr << "Failed to create SSL_CTX." << std::endl;
return -2;
}
if (SSL_CTX_load_verify_locations(m_ctx, NULL, "/etc/ssl/certs") <= 0) { // 设置CA证书路径
std::cerr << "Failed to load CA certificates." << std::endl;
return -3;
}
if (SSL_CTX_use_certificate_file(m_ctx, HTTP_CERT_PEM, SSL_FILETYPE_PEM) <= 0) {
std::cerr << "Failed to load server certificate." << std::endl;
return -4;
}
if (SSL_CTX_use_PrivateKey_file(m_ctx, HTTP_KEY_PEM, SSL_FILETYPE_PEM) <= 0) {
std::cerr << "Failed to load server private key." << std::endl;
return -5;
}
return 0;
}
SSL_CTX* SingletonOpensslInit::GetCtx()
{
return m_ctx;
}
main.cpp
#include "https_client.h"
#include "OpensslInit.h"
#include "api.h"
int main()
{
SingletonOpensslInit::getInstance().Init();
API* api = new API;
api->GetRecordPath();
return 0;
}
make.sh
g++ *.cpp -L/usr/local/lib64 -lssl -lcrypto -levent_openssl -levent -ljsoncpp -o client -ggdb -std=c++11 -Wno-deprecated-declarations