SslConnection::SslConnection()详解

一、🔍 SslConnection::SslConnection() 详解

这个构造函数的主要作用是:

  1. 创建 SSL 对象
  2. 创建 BIO(I/O 缓冲区)
  3. 初始化 SSL 服务器模式
  4. 绑定回调函数(onRead() 处理接收数据)

📌 1. 初始化 SSL 相关对象

SslConnection::SslConnection(const TcpConnectionPtr& conn, SslContext* ctx): ssl_(nullptr)  // SSL对象(加密/解密), ctx_(ctx)  // SSL 上下文, conn_(conn)  // Muduo 连接对象(底层网络传输), state_(SSLState::HANDSHAKE)  // 初始状态:TLS 握手, readBio_(nullptr)  // 读 BIO(接收加密数据), writeBio_(nullptr)  // 写 BIO(存储加密数据), messageCallback_(nullptr)  // 业务逻辑的回调(不一定用得上)

💡 这里主要是初始化了一些成员变量,确保构造对象时数据是干净的。


📌 2. 创建 SSL 上下文

ssl_ = SSL_new(ctx_->getNativeHandle());
if (!ssl_) {LOG_ERROR << "Failed to create SSL object: " << ERR_error_string(ERR_get_error(), nullptr);return;
}

📍 作用

  • 通过 SSL_new(ctx_->getNativeHandle()) 创建 SSL 对象,用于加解密。
  • 如果失败,打印日志并返回。

🔹 ctx_->getNativeHandle() 是什么?

  • 这里的 ctx_SslContext*,表示 SSL 的全局上下文。
  • ctx_->getNativeHandle() 返回的是 OpenSSL 的 SSL_CTX*,它管理 证书、加密方式、TLS 版本等
  • SSL_new() 基于 SSL_CTX* 创建一个 新的 SSL 会话对象,用于该 TCP 连接的数据加解密。

📌 3. 创建 BIO(I/O 缓冲区)

readBio_ = BIO_new(BIO_s_mem());
writeBio_ = BIO_new(BIO_s_mem());if (!readBio_ || !writeBio_) {LOG_ERROR << "Failed to create BIO objects";SSL_free(ssl_);ssl_ = nullptr;return;
}

📍 作用

  • readBio_ = BIO_new(BIO_s_mem()):创建 读 BIO,用于存放接收的加密数据(网络数据)。
  • writeBio_ = BIO_new(BIO_s_mem()):创建 写 BIO,用于存放加密后的待发送数据
  • 这里使用 BIO_s_mem(),表示创建的是 内存 BIO(不会自动关联 socket,手动读写)。
  • 如果创建 BIO 失败,则释放 SSL 资源,防止内存泄露。

📌 4. 绑定 SSL 和 BIO

SSL_set_bio(ssl_, readBio_, writeBio_);

📍 作用

  • 让 OpenSSL 通过 BIO 读写数据,而不是直接操作 socket。
  • readBio_ 存放接收到的加密数据(模拟 OpenSSL 的 SSL_read())。
  • writeBio_ 存放加密后的待发送数据(模拟 SSL_write())。
  • SSL_set_bio() 绑定 BIO 后,SSL_read() 会自动从 readBio_ 读取数据,SSL_write() 会把加密数据存入 writeBio_

💡 这样就实现了 OpenSSL 和 Muduo 的解耦:

  • Muduo 只管传输数据(读写 readBio_writeBio_)。
  • SSL 只管加密/解密(不直接接触网络)。

📌 5. 设置服务器模式

SSL_set_accept_state(ssl_);  // 设置为服务器模式

📍 作用

  • 服务器模式:在 TLS 握手时,服务器等待客户端发起 Client Hello
  • 服务器通过 SSL_accept() 进行 TLS 握手,成功后才能进行加密通信。

📌 6. 设置 SSL 选项

SSL_set_mode(ssl_, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE);

📍 作用

🔹 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER

  • 允许 SSL_write() 使用动态内存,不要求数据缓冲区保持固定位置(适用于异步网络)。

🔹 SSL_MODE_ENABLE_PARTIAL_WRITE

  • 允许 SSL_write() 部分写入,在数据较长时,不会阻塞,而是先写入部分数据,后续继续发送。

📌 7. 绑定数据接收回调

conn_->setMessageCallback(std::bind(&SslConnection::onRead, this, std::placeholders::_1,std::placeholders::_2, std::placeholders::_3));

📍 作用

  • conn_ 是 Muduo 的 TCP 连接,它接收加密数据后,会调用 onRead() 处理。
  • onRead() 主要作用:
    1. 先把 加密数据 写入 readBio_
    2. 调用 SSL_read() 解密数据
    3. 解密后的数据交给业务逻辑处理。

🎯 8. 总结

🚀 整个 SslConnection 的构造逻辑可以总结如下:

  1. 创建 SSL 对象(用于加密/解密)。
  2. 创建 BIOreadBio_ 存接收数据,writeBio_ 存待发送数据)。
  3. 绑定 BIO(让 SSL_read() / SSL_write() 读写 BIO)。
  4. 设置 SSL 服务器模式SSL_set_accept_state())。
  5. 设置 SSL 选项(允许 SSL_write() 使用动态内存、支持部分写入)。
  6. 绑定 onRead() 回调,处理 Muduo 网络层的数据。

💡 9. 你的代码和 Muduo/SSL 之间的关系

  • Muduo 负责底层的 TCP 连接和数据收发
  • SSL 负责 TLS/SSL 加解密,但不直接读写 socket,而是通过 BIO 缓冲区进行数据交互。
  • Muduo 只管传输,SSL 只管加解密,BIO 作为中间桥梁

🚀 这套架构解耦了网络层和加密层,这样可以:

  1. 更灵活:BIO 让 SSL 适配不同的 I/O(可以换成文件、内存等)。
  2. 更高效:Muduo 依旧是 非阻塞 IO,BIO 负责数据缓存,不阻塞线程。
  3. 更安全:SSL 加密的数据 Muduo 无法直接解读,避免安全漏洞。

🛠 10. 你可以改进的地方

异常处理更全面

  • 目前如果 SSL_new() 失败,只是打印日志并 return,可以抛出异常或者返回错误码,更容易排查问题。

考虑 BIO_set_mem_eof_return()

  • BIO_s_mem() 可能会在 BIO_read() 读取完数据后返回 0,导致 SSL_read() 误以为连接断开。可以用:
    BIO_set_mem_eof_return(readBio_, -1);
    BIO_set_mem_eof_return(writeBio_, -1);
    
    这样 SSL_read() 还能继续读取新数据。

这部分代码设计得 很合理,核心逻辑非常清晰,已经符合 高性能、可扩展、解耦的要求!🚀

二、为什么使用BIO_s_mem()

OpenSSL 里 BIO(Basic I/O) 有多种类型,而 BIO_s_mem() 只是其中之一。
你可以理解 BIO 就是 OpenSSL 里数据的输入/输出缓冲区,不同类型的 BIO 代表不同的 I/O 方式。


📌 1. OpenSSL 里的 BIO 类型

OpenSSL 提供了 三种主要 BIO,分别是:

BIO 类型描述适用于
BIO_s_socket()直接操作 socket 读写阻塞式网络编程
BIO_s_mem()纯内存缓冲区,需要手动传输数据非阻塞网络、框架
BIO_s_ssl()直接包裹 SSL*,自动处理内部封装更简单

🚀 你这里用了 BIO_s_mem(),它的特点是:

不会自动关联 socket(灵活,可适配任何网络框架)
手动读写数据(Muduo 负责收发,BIO 只是缓存)
适用于事件驱动框架(如 Muduo)


📌 2. BIO_s_mem() 为什么适合 Muduo?

Muduo 是 非阻塞 + 事件驱动 的框架,而 OpenSSL 默认的 SSL_read() / SSL_write() 设计成了 阻塞式,所以直接用 OpenSSL 的 BIO_s_socket() 会导致阻塞整个事件循环,影响服务器性能。

💡 解决方案:使用 BIO_s_mem() 让 Muduo 负责数据收发,OpenSSL 只管加解密。

🌟 BIO_s_mem() 允许这样做:

  1. Muduo 读取 TCP 数据,然后 写入 readBio_
    BIO_write(readBio_, encryptedData, len);
    
  2. OpenSSL 从 readBio_ 里读取数据并解密
    SSL_read(ssl_, decryptedBuffer, len);
    
  3. OpenSSL 处理完数据,调用 SSL_write() 生成加密数据,存入 writeBio_
    SSL_write(ssl_, plaintextData, len);
    
  4. Muduo 负责从 writeBio_ 读取加密数据并发送给客户端
    BIO_read(writeBio_, encryptedBuffer, len);
    sendToClient(encryptedBuffer, len);
    

这样,Muduo 仍然是非阻塞的,BIO 只是一个中间缓冲区,不会影响 Muduo 的事件循环。


📌 3. 其他 BIO 方式为什么不合适?

🚫 BIO_s_socket() 直接绑定 socket

如果你用了 BIO_s_socket(),那么:

  • SSL_read() / SSL_write() 会直接阻塞,导致 Muduo 线程被卡住。
  • 影响服务器性能,不能高并发处理多个连接。

🚫 BIO_s_ssl() 让 OpenSSL 直接处理 I/O

  • 这个 BIO 适用于简单场景,适合自己管理 socket 的程序,比如同步服务器。
  • 但你用的是 Muduo 事件驱动,要自己控制数据流动,所以不适合。

📌 4. 总结

你这里使用 BIO_s_mem() 的原因:

  1. 适配 Muduo 非阻塞模型,不会让 SSL_read() 阻塞线程。
  2. 灵活控制数据流动,BIO 只是缓冲区,Muduo 仍然管理 TCP 读写。
  3. 高性能,避免 OpenSSL 直接操作 socket 导致的效率问题。

🚀 这就是 BIO_s_mem() 在 Muduo 里的最佳应用场景!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/72152.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python中单例模式应用

数据库连接池单例模式 1. 为什么使用单例模式 创建数据库连接是一个昂贵的过程&#xff08;涉及网络通信、认证等&#xff09;。单例模式的连接池可以在程序启动时初始化一组连接&#xff0c;并在整个生命周期中重用这些连接&#xff0c;而不是每次请求都新建连接。同时还可…

蓝桥 发现环

0发现环 - 蓝桥云课 找到环 不过在最近一次维护网络时&#xff0c;管理员误操作使得某两台电脑之间增加了一条数据链接&#xff0c;于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径&#xff0c;使得这些电脑上的数据传输出现了BUG。 为了恢复正常传输&am…

不同版本的BLE和WiFi有什么区别?

一、蓝牙技术对比&#xff1a;从 Bluetooth 4.0 到 5.3 的演进与室内定位应用 蓝牙技术自推出以来&#xff0c;经历了多次重大升级&#xff0c;每一代都在传输速率、功耗、覆盖范围和功能上有所改进。本文将从 Bluetooth 4.0 到 5.3&#xff0c;逐一对比各版本的特点&#xff0…

看视频学习方法总结

以下是提高教学视频吸收率的系统性方法&#xff0c;结合认知科学原理和实际学习场景&#xff0c;帮助您最大化学习效果&#xff1a; 一、观看前的黄金准备阶段 60秒快速扫描法 用1分钟快速浏览视频目录、章节标题和简介&#xff0c;建立知识框架。荷兰伊拉斯姆斯大学实验表明&…

Basler acA1920-40gc

软件 下载Basler软件 | Basler AG 说明书 ace acA1920-40gc | GigE相机 | Basler | Basler AG 支持PTP同步 在使用 Basler acA1920-40gc 相机和 Polyn View 软件时&#xff0c;确认 PTP&#xff08;Precision Time Protocol&#xff09;同步是否成功&#xff0c;可以通过…

华为hcia——Datacom实验指南——STP工作基本原理及STP/RSTP基本功能配置

什么时候需要用到STP 在二层交换网络中&#xff0c;为了避免环路产生。 什么是STP STP生成树协议&#xff0c;是用来在冗余链路上消除二层环路。在众多交换机中&#xff0c;需要设置出一个根桥&#xff0c;其余的交换机称为非根桥&#xff0c;根桥是整个交换网络的核心&…

【后端】Docker一本通

长期更新补充&#xff0c;建议关注收藏点赞 目录 Docker概述安装部署Docker基本操作使用docker部署tomcat使用docker部署mysql Docker概述 docker是⼀个应⽤级隔离的虚拟化技术docker三大核心概念 镜像&#xff1a;是具有源的所有特征的⼀个标记⽂件 仓库&#xff1a;存放镜像…

linux中断调用流程(arm)

文章目录 ARM架构下Linux中断处理全流程解析&#xff1a;从硬件触发到驱动调用 ⚡**一、中断触发与硬件层响应** &#x1f50c;**1. 设备触发中断** &#x1f4e1; **二、CPU阶段&#xff1a;异常入口与上下文处理** &#x1f5a5;️**1. 异常模式切换** &#x1f504;**2. 跳转…

第十四届蓝桥杯大赛软件赛国赛C/C++大学C组

A 【跑步计划——日期问题】-CSDN博客 B 【残缺的数字】-CSDN博客 C 题目 代码 #include <bits/stdc.h> using namespace std;void change(int &x) {int sum 0, t x;while(t){sum t % 10;t / 10;}x - sum; } int main() {int n;cin >> n;int ans 0;…

汽车低频发射天线介绍

汽车低频PKE天线是基于RFID技术的深度研究及产品开发应用的一种天线&#xff0c;在汽车的智能系统中发挥着重要作用&#xff0c;以下是关于它的详细介绍&#xff1a; 移动管家PKE低频天线结构与原理 结构&#xff1a;产品一般由一个高Q值磁棒天线和一个高压电容组成&#xff…

蓝桥杯web第三天

展开扇子题目&#xff0c; #box:hover #item1 { transform:rotate(-60deg); } 当悬浮在父盒子&#xff0c;子元素旋转 webkit display: -webkit-box&#xff1a;将元素设置为弹性伸缩盒子模型。-webkit-box-orient: vertical&#xff1a;设置伸缩盒子的子元素排列方…

达梦数据库如何查看当前锁表和如何解决锁表问题

达梦数据库查看当前锁表及解决锁表问题的方法如下&#xff1a; 一、查看当前锁表信息 方法1&#xff1a;通过动态视图 V$LOCK 和 V$SESSIONS 联合查询 查询所有锁信息&#xff1a; SELECT * FROM V$LOCK; 关键列说明&#xff1a;TRX_ID&#xff08;事务ID&#xff09;、LTYP…

ubuntu22.04系统如何自建2级ntp服务器

一&#xff1a;ntp服务器详情 服务器型号 系统版本 IP地址 主机名 ntp服务版本 虚拟机8c-32g-1T Ubuntu22.04 10.20.30.2 DMZ-NTP-SERVER 4.2.8p15 二&#xff1a;ntp服务端部署配置脚本 #!/bin/bash # 脚本信息 echo "--------------------------…

计算机毕业设计SpringBoot+Vue.js汽车资讯网站(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

UE5切换关卡函数OpenLevel,输入模式结构体,UI界面

1.输入模式结构体 FInputModeGameOnly&#xff1a;玩家只能与游戏世界交互&#xff0c;UI 不可交互。FInputModeGameAndUI&#xff1a;玩家可以与游戏世界和 UI 同时交互。FInputModeUIOnly&#xff1a;玩家只能与 UI 交互&#xff0c;无法与游戏世界进行互动。 FInputModeGam…

JavaScript系列03-异步编程全解析

本文介绍了异步相关的内容&#xff0c;包括&#xff1a; 回调函数与回调地狱Promise详解async/await语法Generator函数事件循环机制异步编程最佳实践 1、回调函数与回调地狱 JavaScript最初是为处理网页交互而设计的语言&#xff0c;异步编程是其核心特性之一。最早的异步编…

kali liux的下载

Kali Linux | Penetration Testing and Ethical Hacking Linux Distributionhttps://www.kali.org/ VMware虚拟机https://pan.quark.cn/s/aa869ffbf184 【补充一个今天学到的知识昂和内容无关:&#xff08;遥感&#xff09;指非接触的远距离探测技术&#xff0c;使用传感器探…

windows下玩转vllm:在wsl下安装vllm

文章目录 前言安装wsl启动wsl的默认分发使用python部署vllm创建并激活虚拟环境直接说结论试错过程安装vllm简单测试一下,看看行不行附录,安装wsl安装ubuntu分发步骤 3: 设置用户和密码步骤 4: 更新系统步骤 5: 使用 WSL前言 当前,部署通义千问2.5-vl已经是一件箭在弦上,不…

《信息论与编码》课程笔记——绪论和离散信源(一)

目录 绪论 一、信息论的基本概念 1.1 信息的定义 1.2 信息的三个层次 二、香农信息论的研究内容 2.1 信源与信源编码 2.2 信道与信道编码 2.3 保密通信与密码学 离散信源&#xff08;一&#xff09; 一、自信息 1.1 定义 二、离散信源 2.1 定义 2.2 符号表示 三、…

大模型中的Token到底是什么?

文章目录 引言什么是Token&#xff1f;定义举例说明中文Tokenization Tokenization的复杂性子词TokenizationBPE算法BPE示例 可视化BPE过程 Token在大模型中的作用输入表示上下文理解输出生成 Tokenization的挑战语言差异未登录词计算效率 Token消耗的规则Token消耗的基本规则示…