Muduo + OpenSSL 网络交互完整流程

embedded/2025/3/5 0:47:01/

🔥 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 负责真正的传输
整个流程设计合理,兼顾了 安全性高效性!🚀


http://www.ppmy.cn/embedded/170043.html

相关文章

Ubuntu中dpkg命令和apt命令的关系与区别

在 Ubuntu 中&#xff0c;dpkg 和 apt 是软件包管理的核心工具&#xff0c;但二者的角色和功能有显著区别&#xff1a; ​一、功能定位 ​特性​​**dpkg**​​**apt**​​层级​底层工具&#xff08;直接操作 .deb 文件&#xff09;高层工具&#xff08;管理软件仓库和依赖关…

HTML + CSS 题目

1.说说你对盒子模型的理解? 一、是什么 对一个文档进行布局的时候&#xff0c;浏览器渲染引擎会根据标准之一的css基础盒模型&#xff0c;将所有元素表示为一个个矩形的盒子。 一个盒子由四个部分组成: content&#xff0c;padding&#xff0c;border&#xff0c;margin 下…

Windows本地Docker+Open-WebUI部署DeepSeek

最近想在自己的电脑本地部署一下DeepSeek试试&#xff0c;由于不希望污染电脑的Windows环境&#xff0c;所以在wsl中安装了ollama&#xff0c;使用ollama拉取DeepSeek模型。然后在Windows中安装了Docker Desktop&#xff0c;在Docker中部署了Open-WebUI&#xff0c;最后再在Ope…

基于coze+微信小程序的ai对话

界面介绍&#xff1a; 代码&#xff1a;&#xff08;替换你的coze的配置&#xff09; <template><view class"container"><!-- 高斯模糊背景 --><view class"animated-bg"><view class"gradient-blob"></view…

mybatis相关的面试题及答案第一弹

1. MyBatis的核心组件有哪些&#xff1f;它们的作用是什么&#xff1f; 答案&#xff1a; MyBatis的核心组件包括&#xff1a; SqlSessionFactory&#xff1a;负责创建SqlSession对象&#xff0c;是MyBatis的核心工厂。SqlSession&#xff1a;用于执行SQL语句、获取映射器&am…

探秘基带算法:从原理到5G时代的通信变革【六】CRC 校验

文章目录 2.5 CRC 校验2.5.1 前言2.5.2 CRC算法简介2.5.3 CRC计算的详细过程2.5.4 CRC校验的两种方法详解**分离比较法****整体运算法****不同位出错与余数的关系****总结** 2.5.5 CRC计算的C实现及工具介绍**C实现CRC计算****CRC计算工具推荐** **2.5.6 总结&#xff1a;CRC校…

OpenHarmony启动恢复子系统

OpenHarmony启动恢复子系统 简介 启动恢复负责在内核启动之后到应用启动之前的系统关键进程和服务的启动过程的功能。涉及以下组件&#xff1a; init组件 支持使用LiteOS-A和Linux内核的平台。 负责处理从内核加载第一个用户态进程开始&#xff0c;到第一个应用程序启动之间的…

Linux内核配置与构建原理

Kconfig文件 Kconfig是Linux内核中用于配置功能的脚本语言系统&#xff0c;由众多内核源码树中每个目录下的Kconfig文件组成。它定义Linux相关的配置选项层次结构和依赖关系。 menuconfig工具&#xff0c;会抓取Kconfig中的信息&#xff0c;为用户输出友好的交互式菜单选项配…