需要下载安装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;
}