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.pswp.cn/diannao/72152.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/72152.shtml
英文地址,請注明出處:http://en.pswp.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消耗的基本規則示…