C++发起Https连接请求

发布于:2025-05-11 ⋅ 阅读:(19) ⋅ 点赞:(0)

需要下载安装openssl

//stdafx.h
#pragma once
#include<iostream>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <iostream>
#include <string>


#pragma comment(lib, "libssl.lib")
#pragma comment(lib, "libcrypto.lib")
//https.h
#pragma once
#include"stdafx.h"
#include <unordered_map>
using namespace std;
//class Head
//{
//public:
//	string name, value;
//	Head(const char*name,const char*value);
//	Head(string lines);
//	void load_str(string lines);
//};
class Https
{
private:
	bool is_ok,is_connect;
	int ResponseCode;
public:
	std::unordered_map<string, string> ResPons;
	static bool is_init;
	void Init();
	string Url;
	string Host;
	string Url_ssl;
	string request;
	SSL_CTX * ctx;
	BIO* bio;
	Https(string url);
	int connect();
	int getResponseCode();
	void disconnect();
	void set_headers(string headers);
	int read(char*buffer, int len);
	~Https();
};
//https.cpp
#include"https.h"
bool Https::is_init = false;
void Https::Init()
{
	SSL_library_init();
	SSL_load_error_strings();
	OpenSSL_add_all_algorithms();
	Https::is_init = true;
}
void ConfigureUnsafeSSLContext(SSL_CTX* ctx) {
	SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
	SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
}
Https::Https(string url)
{
	if (!Https::is_init)
	{
		Https::Init();
	}
	this->ResponseCode = -1;
	this->is_ok = false;
	this->is_connect = false;
	if (url.find("https://", 0) == -1)
	{
		std::cout << "链接格式不规范" << std::endl;
		return;
	}
	this->is_ok = true;
	int t1 = url.find("/", 8)-8;
	if (t1 <= -1)
		t1 = url.length() - 8;
	this->Host = url.substr(8, t1);
	this->Url = url;
	this->Url_ssl = this->Host;
	this->Url_ssl.append(":https");
	this->set_headers("");
}

int Https::connect()
{
	this->is_connect = true;
	this->ctx = SSL_CTX_new(SSLv23_method());
	if (!ctx) {
		std::cerr << "Error creating SSL context\n";
		ERR_print_errors_fp(stderr);
		return 1;
	}

	// 配置不安全上下文(不验证证书)
	ConfigureUnsafeSSLContext(ctx);

	// 创建BIO连接
	this->bio = BIO_new_ssl_connect(ctx);
	if (!bio) {
		std::cerr << "Error creating BIO\n";
		SSL_CTX_free(ctx);
		return 1;
	}

	// 设置主机和端口
	BIO_set_conn_hostname(bio,this->Url_ssl.c_str());

	// 获取SSL指针
	SSL* ssl = nullptr;
	BIO_get_ssl(bio, &ssl);
	SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

	// 建立连接
	if (BIO_do_connect(bio) <= 0) {
		std::cerr << "Error connecting\n";
		ERR_print_errors_fp(stderr);
		BIO_free_all(bio);
		SSL_CTX_free(ctx);
		return 1;
	}

	// 发送HTTP请求

	if (BIO_write(bio, request.c_str(), request.length()) <= 0) {
		std::cerr << "Error writing request\n";
		ERR_print_errors_fp(stderr);
		BIO_free_all(bio);
		SSL_CTX_free(ctx);
		return 1;
	}
	// 读取响应
	char buffer[1];
	int bytesRead = 0;
	string h1="";
	while ((bytesRead = BIO_read(bio, buffer, sizeof(buffer))))
	{
		if (bytesRead < 0) {
			std::cerr << "Error reading response\n";
			break;
		}
		if (buffer[0] == '\r')
		{
			BIO_read(bio, buffer, sizeof(buffer));
			break;
		}
		h1.push_back(buffer[0]);
	}
	if (h1.find("HTTP/1.1 ") == -1)
		this->ResponseCode = 500;
	h1 = h1.substr(9, h1.find(" OK", 9));
	sscanf_s(h1.c_str(), "%d", &(this->ResponseCode));
	for (int i = 0; i < 1000; i++)
	{
		h1 = "";
		BIO_read(bio, buffer, sizeof(buffer));
		if (buffer[0] == '\r')
		{
			BIO_read(bio, buffer, sizeof(buffer));
			break;
		}
		h1.push_back(buffer[0]);
		while ((bytesRead = BIO_read(bio, buffer, sizeof(buffer))))
		{
			if (bytesRead < 0) {
				std::cerr << "Error reading response\n";
				break;
			}
			if (buffer[0] == '\r')
			{
				BIO_read(bio, buffer, sizeof(buffer));
				break;
			}
			h1.push_back(buffer[0]);
		}
		int sp = h1.find(": ");
		if (sp == -1)
			break;
		string name = h1.substr(0, sp);
		int sp1= h1.find("\r",sp+2);
		if (sp1 == -1)
			sp1 = h1.length() - sp - 2;
		string value= h1.substr(sp+2, sp1);
		this->ResPons.insert(std::make_pair(name, value));
		name.clear();
		value.clear();
	}
	// 清理资源
}

int Https::read(char * buffer, int len)
{
	int bytesRead = BIO_read(bio, buffer, len);
	return bytesRead;
}
int Https::getResponseCode()
{
	return this->ResponseCode;
}

void Https::disconnect()
{
	if (!(this->is_connect))return;
	BIO_free_all(bio);
	SSL_CTX_free(ctx);
	EVP_cleanup();
}

void Https::set_headers(string headers)
{
	this->request = "GET ";
	this->request += this->Url;
	this->request+=" HTTP/1.1\r\n";
	this->request += "Host: ";
	this->request += this->Host.c_str();
	this->request += "\r\n";
	this->request += headers;
	this->request += "\r\n";
	cout << request << endl;
}


Https::~Https()
{
	this->disconnect();
}
//
//Head::Head(const char * name, const char * value)
//{
//	this->name = name;
//	this->value = value;
//}
//
//Head::Head(string lines)
//{
//	this->load_str(lines);
//}
//
//void Head::load_str(string lines)
//{
//	int sp = lines.find(": ");
//	if (sp == -1)
//		return;
//	this->name = lines.substr(0, sp);
//	int sp1= lines.find("\r",sp+2);
//	if (sp1 == -1)
//		sp1 = lines.length() - sp - 2;
//	this->value= lines.substr(sp+2, sp1);
//}

//1.cpp
#include"stdafx.h"
#include"https.h"

int main() {
	Https *h = new Https("https://www.baidu.com/");
	
	h->connect();
	std::cout << h->getResponseCode() << std::endl;
	for (auto it = h->ResPons.begin(); it != h->ResPons.end(); ++it) {
		std::cout << it->first << ": " << it->second << std::endl;
	}
	char t[1024];
	int len1;
	while ((len1 = h->read(t, 1024))>0)
	{
		std::fwrite(t, 1, len1, stdout);
	}
	return 0;
}