当前位置: 首页 > article >正文

Muduo + OpenSSL 网络交互完整流程

🔥 Muduo + OpenSSL 网络交互完整流程

这套架构结合了 Muduo(网络库)+ OpenSSL(TLS/SSL 加密)+ BIO(缓存),整个数据流动过程如下:


🌍 1. 网络通信的基本流程

Muduo 负责 管理连接和数据传输,但它自己不会加密数据,所以我们引入 OpenSSL 来处理 TLS/SSL 加密。

💡 核心思路:

  • 服务器和客户端通过 TCP 连接 进行通信。
  • 数据在 发送之前被 SSL 加密,然后交给 Muduo 发送
  • 数据在 接收后先存入 BIO,SSL 再解密,最后交给业务逻辑处理。

🚀 2. 详细的 SSL 网络交互流程

假设你有 A(客户端)B(服务器),它们之间用 TLS/SSL 进行安全通信。

📌(1)客户端连接服务器

  • 客户端通过 Muduo 发起 TCP 连接,服务器接受连接。
  • 这时候还没开始 SSL/TLS 认证,连接只是普通的 TCP 连接。

📌(2)SSL 握手(TLS/SSL 认证)

👉 目标: 确保数据加密,并建立 SSL 安全通道。
🔹 客户端(A) 发起 SSL 握手

  • 客户端 Muduo 建立连接后,初始化 OpenSSL(SSL_new),使用 BIO 进行 I/O 操作。
  • 通过 SSL_connect() 发送 Client Hello,尝试建立 TLS 连接。

🔹 服务器(B) 处理 SSL 握手

  • 服务器 Muduo 监听到连接后,初始化 SSL_accept() 进行 TLS 认证。
  • 服务器返回 Server Hello,协商 TLS 版本、密钥等信息。

🔸 这一步完成后,A 和 B 之间的通信就会被 TLS/SSL 加密了!


📌(3)客户端发送数据

假设 客户端 A 要发送 "Hello Server"服务器 B,数据流如下:

1️⃣ 应用层调用 SSL_write() 进行加密

SSL_write(ssl_, data, len);
  • SSL 负责加密数据,但不会直接发网络数据,而是把加密后的数据放进 writeBio_

2️⃣ writeBio_ 取出加密数据

int bytes = BIO_read(writeBio_, buf, sizeof(buf));
  • BIO_read() writeBio_ 读取加密数据(即 TLS 加密后的数据)。

3️⃣ Muduo 负责真正发送数据

conn_->send(buf, bytes);
  • Muduo 通过 socket 发送 buf,这时候的数据已经是 加密后的,即 TLS 报文。

📌(4)服务器接收数据

服务器 B 监听到新的 TCP 数据,流程如下:

1️⃣ Muduo 通过 conn_->recv(buf, len) 接收数据

  • 收到的是加密数据(TLS 报文)。

2️⃣ 写入 readBio_ 供 SSL 解密

BIO_write(readBio_, buf, len);
  • 这相当于把加密数据喂给 SSL,让它去解密。

3️⃣ 调用 SSL_read() 解密数据

SSL_read(ssl_, buf, len);
  • 这一步 SSL readBio_ 读取数据并解密,得到 "Hello Server"(明文)。
  • 服务器最终收到 解密后的明文数据,可以正常处理业务逻辑。

📌(5)服务器回传数据

服务器 B 也可以按照相同的方式给 客户端 A 发送加密数据,流程类似:

  1. SSL_write() 加密数据
  2. BIO_read(writeBio_) 取出加密数据
  3. conn_->send(buf, bytes) 通过 Muduo 发送

客户端接收数据后:

  1. conn_->recv(buf, len) 接收 加密数据
  2. BIO_write(readBio_, buf, len) 存入 BIO
  3. SSL_read() 读取并解密,得到明文

🔍 3. 你代码中的数据流

💡 结合你提供的 SslConnection::send() 代码:

void SslConnection::send(const void* data, size_t len) 
{if (state_ != SSLState::ESTABLISHED) {LOG_ERROR << "Cannot send data before SSL handshake is complete";return;}int written = SSL_write(ssl_, data, len);if (written <= 0) {int err = SSL_get_error(ssl_, written);LOG_ERROR << "SSL_write failed: " << ERR_error_string(err, nullptr);return;}char buf[4096];int pending;while ((pending = BIO_pending(writeBio_)) > 0) {int bytes = BIO_read(writeBio_, buf, std::min(pending, static_cast<int>(sizeof(buf))));if (bytes > 0) {conn_->send(buf, bytes);}}
}

📌 代码解析
1️⃣ SSL_write(ssl_, data, len) 进行 TLS 加密,但不会直接发送
2️⃣ BIO_read(writeBio_, buf, len) writeBio_ 取出加密数据
3️⃣ conn_->send(buf, bytes) Muduo 负责真正的网络发送

👉 这里的 conn_->send() 其实就是 Muduo 发送 TCP 数据的封装,最终会调用 send(fd, buf, len, 0)


SSL 与 BIO 读写的详细关系

1. 写数据

🔹 流程:应用层 → SSL 层(加密)→ BIO 层(缓存)→ 网络层

应用程序调用 SSL_write(ssl, 明文数据, 长度)↓
SSL 进行加密,生成加密后的数据↓
加密后的数据被放入 BIO(写 BIO)↓
应用程序调用 BIO_read(writeBio, buf, len)↓
取出加密数据并发送到网络

示例

SSL_write(ssl_, data, len);  // 把明文数据加密并放入 write BIO
int pending = BIO_pending(writeBio_); // 检查加密数据是否可读
BIO_read(writeBio_, buf, pending);  // 取出加密数据
conn_->send(buf, pending);  // 发送到网络

2. 读数据

🔹 流程:网络层 → BIO 层(缓存)→ SSL 层(解密)→ 应用层

数据从网络收到,存入 BIO(读 BIO)↓
应用程序调用 SSL_read(ssl, buf, len)↓
SSL 从 BIO 读取加密数据,并解密↓
返回解密后的明文数据给应用程序

示例

conn_->recv(buf, len);  // 从网络接收数据
BIO_write(readBio_, buf, len);  // 把加密数据存入 read BIO
int bytes = SSL_read(ssl_, buf, sizeof(buf));  // 从 read BIO 取出数据并解密

📌 4. 总结

SSL 读写与 BIO 读写是 逻辑上的两层操作,它们之间的关系可以用一个缓冲区的概念来理解。

🚀 发送数据流程

🔹 应用层:调用 SSL_write() 加密数据
🔹 BIO:加密数据存入 writeBio_
🔹 MuduoBIO_read(writeBio_) 取出数据,conn_->send() 发送

📩 接收数据流程

🔹 Muduoconn_->recv() 接收加密数据
🔹 BIOBIO_write(readBio_, buf, len) 写入 解密 BIO
🔹 应用层:调用 SSL_read() 取出明文数据

  • SSL 不能直接读写 socket,必须通过 BIO 进行数据传输
  • SSL 读写操作的目标是 BIO,而 BIO 负责最终的网络 IO
  • BIO 作为缓冲区存放加密/解密数据,SSL 只负责加密解密
  • 应用程序只操作 SSL_readSSL_write,但实际上 BIO 处理数据的存取

对比理解

操作方向作用
SSL_write(ssl, 明文, 长度)应用层 → BIO明文 → 加密数据放入 BIO
BIO_read(writeBio, buf, len)BIO → 网络读取加密数据,发送
BIO_write(readBio, buf, len)网络 → BIO接收加密数据,存入 BIO
SSL_read(ssl, buf, len)BIO → 应用层BIO 取出加密数据 → 解密成明文

所以,BIO 是 SSL 和实际网络传输之间的桥梁SSL 处理的是加密/解密,BIO 处理的是数据存取和流转


🔹 5. 你的架构的优势

异步非阻塞

  • Muduo 负责网络收发,BIO 作为缓存,不会阻塞线程
    高效解耦
  • SSL 只管加密/解密,Muduo 只管传输,彼此解耦,灵活性高。
    可以适配其他 I/O
  • 你的代码 可以适配不同的传输方式,比如 TCP、UDP,甚至文件存储。

🎯 6. 结论

代码里,SSL 只负责加密,BIO 作为缓存,Muduo 负责真正的传输
整个流程设计合理,兼顾了 安全性高效性!🚀

相关文章:

Muduo + OpenSSL 网络交互完整流程

&#x1f525; Muduo OpenSSL 网络交互完整流程 这套架构结合了 Muduo&#xff08;网络库&#xff09; OpenSSL&#xff08;TLS/SSL 加密&#xff09; BIO&#xff08;缓存&#xff09;&#xff0c;整个数据流动过程如下&#xff1a; &#x1f30d; 1. 网络通信的基本流程 M…...

2025年能源工作指导意见重点内容

一、总体目标 能源供应保障 全国发电总装机容量达到36亿千瓦以上&#xff0c;新增新能源发电装机2亿千瓦以上&#xff0c;发电量目标10.6万亿千瓦时&#xff0c;跨省跨区输电能力持续提升。 煤炭稳产增产&#xff0c;原油产量保持2亿吨以上&#xff0c;天然气产量较快增长&am…...

DNS 详细过程 与 ICMP

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; DNS (Domain Name System) 快速了解&#x1f98b; DNS 背景&#x1f98b; 域名简介&#x1f98b; 真实地址查询 —— DNS&#x1f380; 域名的层级关系&am…...

学到什么记什么(25.3.3)

Upload-labs 今日重新做了一下文件上传漏洞&#xff0c;这里第一题之前采用直接抓包改后缀名.jpg为.php&#xff0c;再写入一句话<?php phpinfo();?>然后放行&#xff0c;得到图片地址&#xff08;可复制&#xff09;&#xff0c;本来直接访问图片地址即可得到敏感信息…...

阿里云服务器部署项目笔记 实操 centos7.9

阿里云服务器部署项目笔记 实操 centos7.9 springboot vue elementUImysqlredis 相关的redis,mysql,nginx镜像,jdk 通过网盘分享的文件&#xff1a;docker镜像 链接: https://pan.baidu.com/s/15VwcWBP4Jy07xADuvylgQw?pwdm2g9 提取码: m2g9 配置环境 连接云服务器 安装…...

完全背包变体-排列和组合的循环顺序问题

排列&#xff0c;区分顺序&#xff1a;内层循环物品{1,2}&#xff0c;可以让3-2->1-1和3-1->2-2都计算一遍。 组合不区分顺序&#xff1a;外层循环物品{1,2}&#xff0c;只会按照物品顺序填充 总结&#xff1a;排列问题中&#xff0c;每个容量的状态更新时&#xff0c;允…...

华为飞腾D2000芯片(基于ARM架构)的欧拉操作系统(openEuler)上部署MySQL

一、环境准备 确认系统架构 uname -m # 应输出 aarch64&#xff08;即ARM64&#xff09;更新系统 sudo dnf update -y安装基础依赖 sudo dnf install -y libaio numactl openssl-devel tar wget二、安装MySQL 方案1&#xff1a;通过openEuler官方仓库安装&#xff08;推荐&am…...

C#开发——日期操作类DateTime

在C#中&#xff0c;日期和时间的操作主要通过 System.DateTime 类来实现。 DateTime 提供了丰富的属性和法&#xff0c;用于处理日期和时间的创建、格式化、比较和计算等操作。以下是一些常用的日期函数和特性&#xff1a; 一、创建日期和时间 1、直接指定日期和时间&…...

win32汇编环境,窗口程序中使控件子类化的示例一

;运行效果 ;win32汇编环境,窗口程序中使编辑框控件子类化的示例一 ;窗口子类化&#xff0c;就是把某种控件&#xff0c;自已再打造一遍&#xff0c;加入自已的功能。比如弄个特殊形状的按钮&#xff0c;或只能输入特殊字符的编辑框 ;当然&#xff0c;一般来说&#xff0c;这都是…...

多镜头视频生成、机器人抓取、扩散模型个性化 | Big Model weekly第58期

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 01 GLM-4-Voice: Towards Intelligent and Human-Like End-to-End Spoken Chatbot 本文介绍了一种名为GLM-4-Voice的智能且类人化的端到端语音聊天机器人。它支持中文和英文&#xff0c;能够进行实时语音对话&a…...

iOS实现一个强大的本地状态记录容器

我们开发中经常会遇到这样的场景&#xff0c;就是我们客户端用户进行了某个操作&#xff0c;这个操作影响了数据的状态&#xff0c;但是我们又不方便重新请求一次数据&#xff0c; 这个时候&#xff0c;就需要我们记录一下本地状态在内存中&#xff0c;随着业务越来越复杂&…...

第十四届蓝桥杯:(二分算法)字串简写

这道题我们的做法是开两个vector&#xff0c;分别把a和b字符的下标存进去&#xff0c;然后遍历a字符&#xff0c;我们要求长度必须大于等于k&#xff0c;我们可以画个图&#xff0c;也就是说b的下标减a的下标必须大于等于k-1 也就是b的下标必须大于等于a的下标k-1 我们用二分找…...

制服小程序的“滑手”:禁用页面左右滑动全攻略

哈哈&#xff0c;看来你已经很聪明地发现了小程序中左右滑动的“顽皮”行为&#xff01;&#x1f604; 没错&#xff0c;我们可以通过设置 disableScroll 属性来“管教”它&#xff0c;同时结合 CSS 样式让页面既禁得住横向“乱跑”&#xff0c;又能顺畅地上下滚动。你的方案已…...

java 实现xxl-job定时任务自动注册到调度中心

xxl-job 自动注册(执行器和任务) 前言 xxl-job是一个功能强大、简单易用、高可用且可扩展性强的分布式定时任务框架/分布式任务调度平台。它适用于各种需要定时任务调度的场景,并可根据业务需求进行灵活配置和扩展。 xxl-job简介 xxl-job是一个开源的分布式定时任务框架,…...

ZK Rollup

ZK Rollup 通过生成零知识证明来确保所有提交的交易都是有效的。生成零知识证明的过程涉及复杂的密码学运算&#xff0c;通常使用的是 zk-SNARK&#xff08;零知识简洁非互动知识论证&#xff09;或 zk-STARK&#xff08;零知识可扩展透明知识论证&#xff09;。以下是 ZK Roll…...

webstorm的Live Edit插件配合chrome扩展程序JetBrains IDE Support实现实时预览html效果

前言 我们平时在前端网页修改好代码要点击刷新再去看修改的效果&#xff0c;这样比较麻烦&#xff0c;那么很多软件都提供了实时预览的功能&#xff0c;我们一边编辑代码一边可以看到效果。下面说的是webstorm。 1 Live Edit 首先我们需要在webstorm的settings里安装插件Live …...

02 HarmonyOS Next仪表盘案例详解(一):基础篇

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; 文章目录 1. 项目概述2. 技术架构2.1 文件结构2.2 ArkTS 语言特性装饰器的使用 3. 数据结构设计3.1 接口定义3.2 数据初始化 4. 生命周期与页面路由…...

张岳教授:语言模型推理与泛化研究 | ICLR 2025 特邀报告与团队专场

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; AITIME 01 ICLR 2025预讲会特邀报告 AITIME 02 ICLR 2025预讲会西湖大学张岳老师实验室专场 01 AI生成文本的自动化检测 Glimpse: Enabling White-Box Methods to Use Proprietary Models for Zero-Shot LLM-Ge…...

离散傅里叶变换(Discrete Fourier Transform, DFT)及其在图像处理中的应用

离散傅里叶变换&#xff08;DFT&#xff09;及其在图像处理中的应用 什么是离散傅里叶变换&#xff1f; 离散傅里叶变换&#xff08;Discrete Fourier Transform, DFT&#xff09;是一种强大的数学工具&#xff0c;用于将离散信号从时域&#xff08;或空间域&#xff09;转换…...

记一次误禁用USB导致键盘鼠标失灵的修复过程

背景说明 在电脑上插入了一个USB hub&#xff0c;然后弹窗提示&#xff1a;“集线器端口上出现电涌”&#xff0c;点开让选择“重置”或者“关闭”&#xff0c;不小心点了关闭&#xff0c;结果这个usb口就被关了&#xff0c;再插任何东西都没反应&#xff0c;找了很多办法都恢…...

Apache nifi demo 实验

Apache nifi 是个数据流系统&#xff0c;可以通过配置 自定义的流程来实现数据的转换。 比如可以配置一个流程&#xff0c;读取数据库里的数据&#xff0c;再转换&#xff0c;最后保存到本地文件。 这样可以来实现一些数据转换的操作&#xff0c;而不用特地编写程序来导入导出。…...

Leetcode 57-插入区间

给你一个 无重叠的 &#xff0c;按照区间起始端点排序的区间列表 intervals&#xff0c;其中 intervals[i] [starti, endi] 表示第 i 个区间的开始和结束&#xff0c;并且 intervals 按照 starti 升序排列。同样给定一个区间 newInterval [start, end] 表示另一个区间的开始和…...

SpringCloud之Eureka、Ribbon、OpenFeign

目录1. SpringCloud Eureka&#xff08;服务注册与发现组件&#xff09;2. SpringCloud Ribbon&#xff08;负载均衡与服务调用组件&#xff09;3. SpringCloud OpenFeign&#xff08;负载均衡与服务调用组件&#xff09;SpringCloud&#xff1a;用于开发高度可扩展、高性能的分…...

如何在MacOS 10.15上安装Docker Desktop

前文提到MacOS 10.15上无法通过Homebrew安装最新版本的docker&#xff0c;自然想到了去安装更早版本的docker。在MacOS上安装Docker Desktop比安装Docker Engine要更方便一些&#xff0c;具体原因可以自己搜索。通过Docker Desktop的Release notes得知最后一个支持MacOS 10.15的…...

Moticon智能鞋垫传感器OpenGo:经济实用的运动科学研究与临床评估工具

Moticon智能鞋垫传感器OpenGo是运动科学研究领域的一款高性能工具&#xff0c;其无线设计和精准传感器为步态分析、平衡评估以及疾病诊断提供了稳定的数据支持。通过实时捕捉足底压力分布、动态变化及平衡状态&#xff0c;OpenGo 为研究人员和临床医生提供了深入洞察个体运动模…...

打造高清3D虚拟世界|零基础学习Unity HDRP高清渲染管线(第一天)

打造高清3D虚拟世界|零基础学习Unity HDRP高清渲染管线&#xff08;第一天&#xff09; 前言最后 前言 说真的&#xff0c;用Unity工作这几年&#xff0c;经历的项目大大小小&#xff0c;对于场景的渲染算是有一定的经验&#xff0c;但涉及到HDRP高清渲染管线的了解&#xff0…...

nlp第十节——LLM相关

一、模型蒸馏技术 本质上是从一个大模型蒸馏出小模型&#xff0c;从小模型训练出来的概率分布&#xff08;如自回归模型预测下一个字的概率分布&#xff09;分别与大模型预测的概率分布和ground label求loss。与大模型预测的概率分布用KL散度求loss&#xff0c;与ground label用…...

Flutter管理项目实战

目录&#xff1a; 1、项目的构建和介绍 1、项目的构建和介绍 登录官网下载flutter的zip压缩包&#xff0c;解压到某个文件夹下即可&#xff0c;里面自带sdk的文件&#xff0c;无需再下载&#xff1b;创建项目时选定flutter的sdk的路径即可创建项目完成。 后续待完善&#xff0…...

智能差旅管理新范式:MyAgent如何重塑企业差旅全流程自动化

在快节奏的商业环境中&#xff0c;企业差旅管理长期面临着流程碎片化、人工操作繁复、合规风险高等痛点。传统模式下&#xff0c;员工需要反复填写纸质表单、逐级跑动审批&#xff0c;财务部门则要耗费大量时间核对票据&#xff0c;这种低效流程每年造成企业平均约15%的差旅管理…...

PostgreSQL 生产环境升级指南:pg_upgrade 快速完成版本升级!

前言 PostgreSQL 的版本号由主要版本号和次要版本号组成。例如&#xff0c;在 10.1 中&#xff0c;10 是主要版本&#xff0c;1 是次要版本。关于更多版本的规划&#xff0c;请参考 PostgreSQL 版本路线图。 版本号规则&#xff1a; PostgreSQL 10 及以后&#xff1a;版本号…...