学懂C++(四十):网络编程——深入详解 HTTP、HTTPS 及基于 Windows 系统的 C++ 实现
目录
一、引言
二、HTTP 协议
1. HTTP 概述
2. HTTP 工作原理
3. HTTP 请求和响应格式
HTTP 请求格式
4. HTTP 状态码
三、HTTPS 协议
1. HTTPS 概述
2. HTTPS 工作原理
四、基于 Windows 系统的 C++ 实现
1. 准备工作
2. HTTP 客户端实现
示例代码
3. HTTPS 客户端实现
示例代码
4. HTTPS 服务器实现
示例代码
五、总结
一、引言
在现代互联网中,HTTP 和 HTTPS 是两种最常见的应用层协议,用于在客户端(如浏览器)和服务器之间传输数据。理解这两种协议的工作原理、区别及其在 C++ 中的实现,对于网络编程开发者来说至关重要。本文将深入解析 HTTP 和 HTTPS 的基础概念、工作原理及其在 Windows 环境下使用 C++ 进行实现的详细过程。
二、HTTP 协议
1. HTTP 概述
HTTP (Hypertext Transfer Protocol) 是一种应用层协议,用于分布式、协作式和超媒体信息系统。HTTP 是万维网的数据通信基础,主要特点包括:
- 无状态:每个 HTTP 请求都是独立的,服务器不保留请求间的状态。
- 简单灵活:易于实现和扩展,支持多种数据类型。
- 面向请求/响应模型:客户端发送请求,服务器返回响应。
2. HTTP 工作原理
HTTP 使用 TCP 作为传输层协议,遵循以下典型的请求/响应模型:
- 客户端与服务器建立 TCP 连接。
- 客户端发送 HTTP 请求,包含请求行、请求头和可选的请求体。
- 服务器处理请求并返回 HTTP 响应,包含状态行、响应头和可选的响应体。
- 关闭连接或保持连接,根据连接的设置(如
Connection: keep-alive
)。
3. HTTP 请求和响应格式
HTTP 请求格式
请求行:方法 URL 版本
请求头:头部字段名: 值
空行
请求体(可选)
示例:
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
HTTP 响应格式
状态行:版本 状态码 状态消息
响应头:头部字段名: 值
空行
响应体(可选)
示例:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 123<html>...</html>
4. HTTP 状态码
HTTP 状态码表示服务器对请求的处理结果,常见的状态码包括:
- 1xx (信息):请求已接收,继续处理。
- 2xx (成功):请求成功,常见如
200 OK
。 - 3xx (重定向):需要进一步操作以完成请求,常见如
301 Moved Permanently
。 - 4xx (客户端错误):请求包含语法错误或无法完成,常见如
404 Not Found
。 - 5xx (服务器错误):服务器在处理请求时发生错误,常见如
500 Internal Server Error
。
三、HTTPS 协议
1. HTTPS 概述
HTTPS (Hypertext Transfer Protocol Secure) 是一种通过 SSL/TLS 协议进行加密的 HTTP 协议,用于在客户端和服务器之间建立安全的通信通道。HTTPS 增强了 HTTP 的安全性,主要特点包括:
- 加密:保护数据在传输过程中不被窃听。
- 身份验证:验证服务器身份,防止中间人攻击。
- 数据完整性:确保数据在传输过程中不被篡改。
2. HTTPS 工作原理
HTTPS 使用 SSL/TLS 协议对数据进行加密,典型的工作流程如下:
- 客户端发起 HTTPS 连接请求。
- 服务器返回 SSL/TLS 证书,包含服务器的公钥。
- 客户端验证证书的合法性,生成对称密钥,并使用服务器公钥加密该密钥。
- 服务器使用私钥解密密钥,建立加密通信通道。
- 客户端与服务器进行加密通信。
四、基于 Windows 系统的 C++ 实现
1. 准备工作
在 Windows 系统上使用 C++ 进行 HTTP 和 HTTPS 通信,可以使用 Windows API 或开源库(如 libcurl)。本文将使用 Windows API 进行示例演示。
2. HTTP 客户端实现
示例代码
#include <windows.h> // 包含 Windows API 函数和常量
#include <wininet.h> // 包含 Windows Internet 函数
#include <iostream> // 包含输入输出流
#pragma comment(lib, "wininet.lib") // 链接 wininet 库int main() {// 初始化 Internet 句柄HINTERNET hInternet = InternetOpen(L"MyHTTPClient", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);if (!hInternet) {std::cerr << "InternetOpen failed: " << GetLastError() << std::endl;return -1;}// 连接到指定的服务器HINTERNET hConnect = InternetConnect(hInternet, L"www.example.com", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);if (!hConnect) {std::cerr << "InternetConnect failed: " << GetLastError() << std::endl;InternetCloseHandle(hInternet);return -1;}// 创建一个 HTTP 请求句柄HINTERNET hRequest = HttpOpenRequest(hConnect, L"GET", L"/index.html", NULL, NULL, NULL, 0, 0);if (!hRequest) {std::cerr << "HttpOpenRequest failed: " << GetLastError() << std::endl;InternetCloseHandle(hConnect);InternetCloseHandle(hInternet);return -1;}// 发送 HTTP 请求if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) {std::cerr << "HttpSendRequest failed: " << GetLastError() << std::endl;InternetCloseHandle(hRequest);InternetCloseHandle(hConnect);InternetCloseHandle(hInternet);return -1;}// 读取服务器响应的数据char buffer[4096];DWORD bytesRead;while (InternetReadFile(hRequest, buffer, sizeof(buffer) - 1, &bytesRead) && bytesRead) {buffer[bytesRead] = '\0'; // 添加字符串终止符std::cout << buffer; // 输出响应内容}// 关闭句柄InternetCloseHandle(hRequest);InternetCloseHandle(hConnect);InternetCloseHandle(hInternet);return 0;
}
解析:
- InternetOpen:初始化使用
wininet
的应用程序。- InternetConnect:连接到指定的服务器。
- HttpOpenRequest:创建一个 HTTP 请求句柄。
- HttpSendRequest:发送 HTTP 请求。
- InternetReadFile:读取服务器响应的数据。
3. HTTPS 客户端实现
示例代码
#include <windows.h> // 包含 Windows API 函数和常量
#include <wininet.h> // 包含 Windows Internet 函数
#include <iostream> // 包含输入输出流
#pragma comment(lib, "wininet.lib") // 链接 wininet 库int main() {// 初始化 Internet 句柄HINTERNET hInternet = InternetOpen(L"MyHTTPSClient", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);if (!hInternet) {std::cerr << "InternetOpen failed: " << GetLastError() << std::endl;return -1;}// 连接到指定的 HTTPS 服务器HINTERNET hConnect = InternetConnect(hInternet, L"www.example.com", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);if (!hConnect) {std::cerr << "InternetConnect failed: " << GetLastError() << std::endl;InternetCloseHandle(hInternet);return -1;}// 创建一个 HTTPS 请求句柄HINTERNET hRequest = HttpOpenRequest(hConnect, L"GET", L"/index.html", NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0);if (!hRequest) {std::cerr << "HttpOpenRequest failed: " << GetLastError() << std::endl;InternetCloseHandle(hConnect);InternetCloseHandle(hInternet);return -1;}// 发送 HTTPS 请求if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) {std::cerr << "HttpSendRequest failed: " << GetLastError() << std::endl;InternetCloseHandle(hRequest);InternetCloseHandle(hConnect);InternetCloseHandle(hInternet);return -1;}// 读取服务器响应的数据char buffer[4096];DWORD bytesRead;while (InternetReadFile(hRequest, buffer, sizeof(buffer) - 1, &bytesRead) && bytesRead) {buffer[bytesRead] = '\0'; // 添加字符串终止符std::cout << buffer; // 输出响应内容}// 关闭句柄InternetCloseHandle(hRequest);InternetCloseHandle(hConnect);InternetCloseHandle(hInternet);return 0;
}
解析: 与 HTTP 客户端的实现类似,主要区别在于:
- InternetConnect 中使用
INTERNET_DEFAULT_HTTPS_PORT
。- HttpOpenRequest 中使用
INTERNET_FLAG_SECURE
标志。
4. HTTPS 服务器实现
基于 Windows 的 C++ 实现 HTTPS 服务器相对复杂,通常建议使用开源库(如 OpenSSL)来处理 SSL/TLS 加密。以下是一个简单的 HTTPS 服务器示例,使用 OpenSSL 进行 SSL/TLS 加密。
示例代码
#include <iostream> // 包含输入输出流
#include <openssl/ssl.h> // 包含 OpenSSL 函数和常量
#include <openssl/err.h> // 包含 OpenSSL 错误处理函数
#include <unistd.h> // 包含 POSIX 操作系统 API
#include <netinet/in.h> // 包含网络库
#include <arpa/inet.h> // 包含网络库#define PORT 8080
#define CERT_FILE "server.crt" // 证书文件路径
#define KEY_FILE "server.key" // 密钥文件路径// 初始化 OpenSSL 库
void init_openssl() {SSL_load_error_strings(); // 加载错误字符串OpenSSL_add_ssl_algorithms(); // 加载加密算法
}// 清理 OpenSSL 库
void cleanup_openssl() {EVP_cleanup(); // 清理加密算法
}// 创建 SSL 上下文
SSL_CTX* create_context() {const SSL_METHOD *method;SSL_CTX *ctx;method = SSLv23_server_method(); // 创建服务器方法ctx = SSL_CTX_new(method); // 创建新 SSL 上下文if (!ctx) {perror("Unable to create SSL context");ERR_print_errors_fp(stderr);exit(EXIT_FAILURE);}return ctx;
}// 配置 SSL 上下文,加载证书和私钥
void configure_context(SSL_CTX *ctx) {SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM); // 加载证书文件SSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, SSL_FILETYPE_PEM); // 加载私钥文件
}int main() {int sockfd;struct sockaddr_in addr;init_openssl(); // 初始化 OpenSSLSSL_CTX *ctx = create_context(); // 创建 SSL 上下文configure_context(ctx); // 配置 SSL 上下文sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建套接字if (sockfd < 0) {perror("Unable to create socket");exit(EXIT_FAILURE);}addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { // 绑定套接字perror("Unable to bind");exit(EXIT_FAILURE);}if (listen(sockfd, 1) < 0) { // 监听连接perror("Unable to listen");exit(EXIT_FAILURE);}while (1) {struct sockaddr_in addr;uint len = sizeof(addr);SSL *ssl;int client = accept(sockfd, (struct sockaddr*)&addr, &len); // 接受客户端连接if (client < 0) {perror("Unable to accept");exit(EXIT_FAILURE);}ssl = SSL_new(ctx); // 创建新 SSL 结构SSL_set_fd(ssl, client); // 关联 SSL 结构和客户端套接字if (SSL_accept(ssl) <= 0) { // SSL 握手ERR_print_errors_fp(stderr);} else {const char reply[] = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello, HTTPS!";SSL_write(ssl, reply, strlen(reply)); // 发送响应}SSL_shutdown(ssl); // 关闭 SSL 连接SSL_free(ssl); // 释放 SSL 结构close(client); // 关闭客户端套接字}close(sockfd); // 关闭服务器套接字SSL_CTX_free(ctx); // 释放 SSL 上下文cleanup_openssl(); // 清理 OpenSSLreturn 0;
}
解析:
- init_openssl:初始化 OpenSSL 库。
- create_context:创建 SSL 上下文。
- configure_context:配置 SSL 上下文,加载证书和私钥。
- socket、bind、listen:创建、绑定和监听套接字。
- accept:接受客户端连接,使用 SSL 处理加密通信。
五、总结
本文深入解析了 HTTP 和 HTTPS 的基础概念、工作原理及其在 Windows 系统下使用 C++ 进行实现的方法。通过详细的示例代码和解析,展示了如何使用 Windows API 和 OpenSSL 库实现 HTTP 和 HTTPS 客户端及服务器。希望本文能帮助读者更好地理解和掌握 HTTP、HTTPS 及其在 C++ 中的实现,提高网络编程技能。
相关文章:

学懂C++(四十):网络编程——深入详解 HTTP、HTTPS 及基于 Windows 系统的 C++ 实现
目录 一、引言 二、HTTP 协议 1. HTTP 概述 2. HTTP 工作原理 3. HTTP 请求和响应格式 HTTP 请求格式 4. HTTP 状态码 三、HTTPS 协议 1. HTTPS 概述 2. HTTPS 工作原理 四、基于 Windows 系统的 C 实现 1. 准备工作 2. HTTP 客户端实现 示例代码 3. HTTPS 客户…...

Element-06.案例
一.目标 实现下面这个页面,表格中的数据使用axois异步加载数据 二.实现步骤 首先在vue项目的views文件夹中新建一个tlias文件夹,用来存储该案例的相关组件。员工页面组件(EmpView.vue)和部门页面组件(DeptView.vue&…...

Axure高端交互元件库:助力产品与设计
用户体验(UX)和用户界面(UI)设计对于任何产品的成功都至关重要。为了在这个竞争激烈的市场中脱颖而出,设计师和产品开发团队需要依赖强大的工具来创造引人注目且功能丰富的交互界面。下面介绍一款Axure精心制作的"…...

后端开发刷题 | 二叉树的前序遍历
描述 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 数据范围:二叉树的节点数量满足 1≤n≤100 ,二叉树节点的值满足 1≤val≤100,树的各节点的值各不相同 示例 1: 示例1 输入: {1,#,2,3} 返…...

自动化之响应式Web设计:纯HTML和CSS的实现技巧
大家好,我是程序员小羊! 前言 响应式Web设计是一种使Web页面在各种设备和屏幕尺寸下都能良好显示的设计方法。随着移动设备的普及,响应式设计已经成为Web开发中的标准实践。本文将探讨如何使用纯HTML和CSS实现响应式Web设计,覆…...

SolarMarker 正在使用水坑攻击与伪造的 Chrome 浏览器更新进行攻击
在过去的三个月里,eSentire 的安全研究团队发现信息窃密恶意软件 SolarMarker 都没有发动攻击,却在最近忽然重返舞台。此前,SolarMarker 的运营者使用 SEO 投毒或者垃圾邮件来引诱受害者,受害者试图下载一些文档的免费模板&#x…...

uView的u-notice-bar组件横向滚动不生效问题解决
uView的u-notice-bar组件横向滚动不生效问题解决 此问题导致我换了vant组件的 notice-bar,一度以为是该组件存在bug。uniapp中有vant组件打包小程序又是一个问题,于是乎不得不回来继续折腾uView的u-notice-bar组件,偶然发现css属性animation-…...

基于免疫算法的最优物流仓储点选址方案MATLAB仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于免疫算法的最优物流仓储点选址方案MATLAB仿真。 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 (完整程序运行后无水印) 3…...

基于Java爬取微博数据(三) 微博主页用户数据
基于Java爬取微博数据三 微博主页用户数据 数据分析爬取数据注意点 上一篇文章简单讲述了基于Java爬取微博数据(二),那么这篇将讲述如何基于 Java 爬取微博主页用户数据,下面开始具体的操作。 数据分析 在开始爬取微博主页用户数据之前,我们…...

Openstack 与 Ceph集群搭建(中): Ceph部署
文章目录 一、部署前说明1. ceph 版本选择依据2. ceph网络要求3. 硬件要求 二、部署架构三、部署过程1. 通用步骤2. 部署管理节点创建账号安装Cephadm运行bootstrap 3. 登录Ceph web4. 将其他节点加入集群同步ceph key安装ceph CLI命令行添加主机节点到集群添加OSD节点将监控节…...

上市公司上下游、客户数据匹配数据集(2001-2023年)
参考《中国工业经济》中陶锋(2023)的做法,对上市公司的上下游供应商和客户数据进行匹配。形成“上游供应商—目标企业—下游客户一年度数据集” 一、数据介绍 数据名称:上市公司-上下游和客户数据匹配 数据范围:上市…...

Promise 对象
Promise 对象是 JavaScript 中用于处理异步操作的一种机制。它代表了一个最终可能完成(fulfilled)或失败(rejected)的异步操作及其结果值。Promise 对象使得异步代码更加容易编写、理解和维护,因为它提供了一种链式调用…...

扫码头测试检测适配步骤
需求分析:适配扫码头看是否能正常工作即适配其能否调用相应的节点其能点亮扫码头并进一步获取其扫码的值。 1.首先先检验其串口是否正常通讯。 2.检验扫码头是否正常工作。 3.上电后拉高是否正常操作触发脚拉高其扫码头有无正常点亮。 4.按侧边键是否正常点亮扫…...

解决k8s分布式集群,子节点加入到主节点失败的问题
1.问题情况 Master主节点在 使用 kubeadm init 成功进行初始化后,如下所示 Your Kubernetes control-plane has initialized successfully!To start using your cluster, you need to run the following as a regular user:mkdir -p $HOME/.kubesudo cp -i /etc/k…...

什么是XSS跨站攻击?如何防护?
什么是XSS跨站攻击?如何防护? 什么是XSS攻击 XSS攻击,即跨站脚本攻击(Cross-Site Scripting),是一种常见的网络安全威胁。其本质是通过在网页中注入恶意的脚本代码,当其他用户浏览这些网页时&…...

谷粒商城实战笔记-问题记录-首页没有显示用户名-跨域session问题
文章目录 一,首页无用户信息二,定位三,两个问题1,跨域名session共享 一,首页无用户信息 谷粒商城首页,点击超链接您好,请登录,正常情况下应该跳转到Auth模块的login页面,…...

【面试宝典】redis常见面试题总结(上)
一、为什么使用 redis? 使用缓存的目的就是提升读写性能。为了提高读写性能,带来更高的并发量。减少对 MySQL 的请求量。 二、redis 有哪些好处? 读写速度快,因为数据存储在内存中,所以数据获取快。支持多种数据结构…...

数据仓库: 3- ETL过程
目录 3- ETL过程3.1 数据抽取(Extract)3.1.1 数据抽取的挑战3.1.2 数据抽取的方式3.1.2.1 全量抽取3.1.2.2 增量抽取3.1.2.3 实时抽取 3.1.3 数据抽取的技术3.1.4 数据抽取工具3.1.5 总结 3.2 数据转换(Transform)3.2.1 定义3.2.2…...

js数组变字符串
let array [1,2,3]; let string array.join(,); // 使用空格作为分隔符 console.log(string); // 输出: "1,2,3"...

日常问题笔记1
th:insert:将被引用的模板片段插⼊到自己的标签体中 th:replace:将被引用的模板片段替换掉自己 th:include:类似于 th:insert,⽽不是插⼊⽚段,它只插⼊此⽚段的内容 <!--1、比如抽取的公用代码片段如下--> <…...

位图与布隆过滤器 —— 海量数据处理
🌈 个人主页:Zfox_ 🔥 系列专栏:C从入门到精通 目录 🚀 位图 一: 🔥 位图概念 二: 🔥 位图的实现思路及代码实现三: 🔥 位图的应用四:…...

二:《Python基础语法汇总》— 条件判断与循环结构
一:条件判断 1.程序执行的三大流程: 顺序流程:无缩进代码,从上往下依次执行 分支流程:选择性执行某块代码,或跳过某行代码去执行,与缩进(TAB)有关 循环流程&…...

【威锋网-注册安全分析报告-无验证方式导致安全隐患】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…...

01_React简介、基础入门
React 简介、基础入门 一、React 简介1、是什么?2、谁开发的?3、为什么要学?4、React 的特点5、学习 React 之前你要掌握的 Javascript 基础知识 二、React 入门1、相关 js 库2、Hello React 入门小例子---React16.8.0 版本3、为什么不用 js …...

【Java 内存区域】
Java内存区域 JDK1.7 VS JDK1.8堆 (Heap)方法区 (Method Area)String 常量池 (String Pool)运行时常量池 (Runtime Constant Pool)虚拟机栈 (JVM Stack)局部变量表操作数栈动态链接方法返回信息 本地方法栈 (Native Method Stack)程序计数器 (Program Counter Register)元空间 …...

你是如何克服编程学习中的挫折感的?
一:学习之路 在编程学习的过程中,挫折和挑战是不可避免的。面对这些困难,我个人的一些经验和方法如下,或许能为你提供一些启示: 1. 学会分解问题 当遇到复杂的算法或者Bug时,我会将问题分解成更小的部分。…...

【AI应用实战】灵办AI插件集成详细指南
一、写在前面 随着AI技术的日新月异,大型模型应用如雨后春笋般涌现,从ChatGPT到文心一言,再到讯飞星火,无一不彰显着智能科技的无限潜力。而在这股浪潮中,我们欣喜地发现,一些创新的浏览器插件正悄然兴起&a…...

MySQL数据库连接超时问题排查报告
1、问题描述 边端设备访问云端过程中有概率出现MySQL数据库连接超时报错,具体报错代码如下: [2024-08-13 13:47:44,036] ERROR in app: Exception on /est-tasks/start [POST] Traceback (most recent call last): File "/usr/local/lib/python3.1…...

代码随想录第三天 | 链表
文章目录 链表理论知识定义链表删除链表 Leetcode203 移除链表元素代码实现 Leetcode707 设计链表代码实现复杂度分析错误点 Leetcode206 反转链表新建链表双指针法 链表理论知识 链接: https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.h…...

Python编码系列—Python数据可视化:Matplotlib与Seaborn的实战应用
🌟🌟 欢迎来到我的技术小筑,一个专为技术探索者打造的交流空间。在这里,我们不仅分享代码的智慧,还探讨技术的深度与广度。无论您是资深开发者还是技术新手,这里都有一片属于您的天空。让我们在知识的海洋中…...