【boost網絡庫從青銅到王者】第三篇:asio網絡編程中的buffer緩存數據結構

文章目錄

  • 1、關于buffer數據結構
      • 1.1、簡單概括一下,我們可以用buffer() 函數生成我們要用的緩存存儲數據。
      • 1.2、但是這太復雜了,可以直接用buffer函數轉化為send需要的參數類型:
      • 1.3、output_buf可以直接傳遞給該send接口。我們也可以將數組轉化為send接受的類型
      • 1.4、對于流式操作,我們可以用streambuf,將輸入輸出流和streambuf綁定,可以實現流式輸入和輸出

1、關于buffer數據結構

任何網絡庫都有提供buffer的數據結構,所謂buffer就是接收和發送數據時緩存數據的結構

boost::asio提供了asio::mutable_bufferasio::const_buffer這兩個結構,他們是一段連續的空間,首字節存儲了后續數據的長度。

asio::mutable_buffer用于寫服務,asio::const_buffer用于讀服務。但是這兩個結構都沒有被asioapi直接使用。

對于apibuffer參數,asio提出了MutableBufferSequenceConstBufferSequence概念,他們是由多個asio::mutable_bufferasio::const_buffer組成的。也就是說boost::asio為了節省空間,將一部分連續的空間組合起來,作為參數交給api使用。

我們可以理解為MutableBufferSequence的數據結構為std::vector<asio::mutable_buffer>

結構如下:
在這里插入圖片描述
每隔vector存儲的都是mutable_buffer的地址,每個mutable_buffer第一個字節表示數據的長度,后面跟著數據內容。

這么復雜的結構交給用戶使用并不合適,所以asio提出了buffer()函數,該函數接收多種形式的字節流,該函數返回asio::mutable_buffers_1 或者asio::const_buffers_1結構的對象。

如果傳遞給buffer()的參數是一個只讀類型,則函數返回asio::const_buffers_1 類型對象。

如果傳遞給buffer()的參數是一個可寫類型,則返回asio::mutable_buffers_1 類型對象。

asio::const_buffers_1asio::mutable_buffers_1asio::mutable_bufferasio::const_buffer的適配器,提供了符合MutableBufferSequenceConstBufferSequence概念的接口,所以他們可以作為boost::asioapi函數的參數使用。

1.1、簡單概括一下,我們可以用buffer() 函數生成我們要用的緩存存儲數據。

比如boost的發送接口send要求的參數為ConstBufferSequence類型:

template<typename ConstBufferSequence>
std::size_t send(const ConstBufferSequence & buffers);

我們需要將 “Hello World” 類型轉換為該類型。

void BoostAsio::UseConstBuffer(std::string& buffer) {boost::asio::const_buffer asio_buff(buffer.c_str(), buffer.length());std::vector<boost::asio::const_buffer> buffer_sequence;buffer_sequence.emplace_back(asio_buff);
}

這段代碼使用了C++編程語言和Boost.Asio庫來處理網絡和異步I/O操作。代碼主要功能是從一個std::string對象創建一個Boost.Asio的const_buffer,然后將這個const_buffer添加到一個const_buffer對象的向量中,通常在需要使用Boost.Asio進行網絡數據傳輸時會這樣做。

  • UseConstBuffer函數:UseConstBuffer函數以一個引用參數buffer作為輸入。函數的目的是創建一個const_buffer,然后將其添加到一個const_buffer對象的向量中。

  • 創建const_buffer:代碼使用buffer.c_str()(字符串c風格表示)和buffer.length()(字符串長度)作為參數,創建了一個名為asio_buffconst_bufferconst_buffer表示一個常量數據的緩沖區,用于讀取操作。

  • 準備緩沖區序列:創建一個名為buffer_sequencestd::vector,用于存儲boost::asio::const_buffer的實例。emplace_back函數將asio_buff添加到buffer_sequence中。

  • 到此為止,buffer_sequence中會包含一個代表輸入std::string的const_buffer

  • 然而,有一個重要的方面需要考慮:buffer_sequence的作用域。目前,buffer_sequence是在UseConstBuffer函數內部定義的局部變量。如果你希望在函數外部使用buffer_sequence,你需要通過返回值或通過引用參數將其傳遞出來。

  • 另外,請確保在代碼的其他部分使用了buffer_sequence來進行實際的網絡操作,例如使用Boost.Asio函數將數據發送到網絡套接字上。

  • 最后,記得正確處理buffer參數引用的std::string對象的生命周期。由于const_buffer引用了字符串的底層字符數據,確保在使用緩沖區期間字符串保持有效。

emplace_back()和push_back()的區別:
在你的代碼中,使用了emplace_back()函數來將asio_buff添加到buffer_sequence中。emplace_back()是C++標準庫中std::vector的一個函數,用于在容器的末尾構造一個新元素。

與之相比,push_back()函數是另一個向std::vector中添加元素的函數,但它要求你傳遞一個已構造的元素(對象)。這意味著如果你使用push_back(),你需要首先創建一個const_buffer對象,然后將其傳遞給函數。而使用emplace_back(),你可以直接在容器中構造新元素,而不需要提前創建對象。

總的來說,emplace_back()通常會比 push_back() 更高效,因為它可以避免額外的對象構造和拷貝操作。在你的代碼中,使用emplace_back()來添加asio_buff是一個不錯的選擇,因為它允許直接在容器中構造const_buffer對象。

  • 對象構造次數:

    • push_back()接受一個已經構造好的對象,并將其副本添加到容器中。這意味著對象需要在調用push_back()之前構造好,然后在添加到容器時還需要執行拷貝構造或移動構造操作。
    • emplace_back()在容器內部直接構造對象,避免了先構造然后拷貝或移動的步驟。它會將傳遞的參數直接用于對象的構造。
  • 拷貝和移動操作:

    • 在使用push_back()時,如果添加的對象是已經構造好的,就需要執行一次拷貝構造(如果容器中的對象類型支持拷貝構造)或移動構造(如果支持移動構造)操作,將對象的副本添加到容器中。
    • 使用emplace_back()時,對象會直接在容器內部構造,避免了拷貝和移動操作。
  • 內存分配:

    • 當使用push_back()添加對象時,它首先會分配內存用于存儲對象的副本,然后執行拷貝或移動操作,最后調整容器的大小。這可能涉及到多次內存分配和釋放。
    • 使用emplace_back()時,它直接在容器內構造對象,避免了額外的內存分配和釋放。
    • 總之,emplace_back()通常更高效,因為它在容器內部直接構造對象,避免了額外的拷貝和移動操作,以及不必要的內存分配和釋放。這使得在需要向容器添加構造對象的情況下,emplace_back()更為優越。

1.2、但是這太復雜了,可以直接用buffer函數轉化為send需要的參數類型:

void BoostAsio::UseConstBuffer1(std::string& buffer) {boost::asio::const_buffers_1 out_buffer(boost::asio::buffer(buffer));
}

代碼段中使用了Boost.Asio庫來創建一個const_buffers_1對象,并通過boost::asio::buffer(buffer)std::string轉換為用于網絡傳輸的緩沖區。讓我對這段代碼進行解釋:

  • 函數名稱和參數:

    • 這個函數名是UseConstBuffer1,它接受一個std::string&類型的參數buffer,傳入的字符串是要被發送的數據。
  • 創建const_buffers_1對象:

    • const_buffers_1Boost.Asio庫中的一個類,用于包裝一個常量緩沖區,以便進行異步I/O操作。
    • 通過boost::asio::buffer(buffer),將buffer(std::string)轉換為一個Boost.Asio緩沖區對象。

在代碼中,盡管你創建了一個const_buffers_1對象,但是這個對象在函數結束后會被銷毀,所以你需要在代碼中繼續使用這個對象進行實際的網絡操作,例如發送數據到套接字。

1.3、output_buf可以直接傳遞給該send接口。我們也可以將數組轉化為send接受的類型

void BoostAsio::UseBufferArray() {const size_t buf_size = 30;std::unique_ptr<char[]> buf(new char[buf_size]);auto input_buf = boost::asio::buffer(static_cast<void*>(buf.get()), buf_size);
}

這段代碼執行以下操作:

  • 定義緩沖區大小:

    • buf_size 是一個常量,表示緩沖區的大小,這里設置為 30 字節。
  • 創建緩沖區數組:

    • 使用 std::unique_ptr 創建了一個 char 數組,大小為 buf_size
    • std::unique_ptr<char[]> 是一個智能指針,用于管理動態分配的 char 數組。這樣做可以在結束作用域時自動釋放內存。
  • 創建輸入緩沖區:

    • 使用 boost::asio::buffer 函數創建了一個輸入緩沖區。
    • buffer 函數的第一個參數是一個 void* 指針,它指向數據的起始地址。在這里,使用 buf.get() 獲取 std::unique_ptr 所管理的原始指針。
    • 第二個參數是緩沖區的大小,即 buf_size

總之,這段代碼的目的是創建一個大小為 30 字節的輸入緩沖區,其中使用了 std::unique_ptr 來管理動態分配的內存。這個緩沖區可以在異步 I/O 操作中使用,比如異步讀取數據到這個緩沖區中。記得在實際應用中,你需要使用 boost::asio::io_context 和套接字等組件來實現具體的異步 I/O 操作。

1.4、對于流式操作,我們可以用streambuf,將輸入輸出流和streambuf綁定,可以實現流式輸入和輸出

id use_stream_buffer() {asio::streambuf buf;std::ostream output(&buf);// Writing the message to the stream-based buffer.output << "Message1\nMessage2";// Now we want to read all data from a streambuf// until '\n' delimiter.// Instantiate an input stream which uses our // stream buffer.std::istream input(&buf);// We'll read data into this string.std::string message1;std::getline(input, message1);// Now message1 string contains 'Message1'.
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/38554.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/38554.shtml
英文地址,請注明出處:http://en.pswp.cn/news/38554.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

docker發展歷史

docker 一、docker發展歷史很久以前2013年2014年2015年2016年2017年2018年2019年及未來 二、 docker概述定義&#xff1a;docker底層運行原理:docker簡述核心概念容器特點Docker與虛擬機的區別: 三、容器在內核中支持兩種重要技術四、namespace的六項隔離五、虛擬化產品有哪些1…

CAS 的執行流程 ?CAS 中 ABA 問題如何解決 ?CAS 在 Java 中有哪些實現類 ?

目錄 1. CAS 的執行流程 2. CAS 中的 ABA 問題 3. 如何解決 CAS 中的 ABA 問題 4.CAS 在Java 中的實現類有哪些 1. CAS 的執行流程 CAS 比較并替換的大致流程是這樣的&#xff1a; 它有三個操作單位&#xff1a;V&#xff08;內存值&#xff09;&#xff0c;A&#xff08;…

3D沉浸式旅游網站開發案例復盤【Three.js】

Plongez dans Lyon網站終于上線了。 我們與 Danka 團隊和 Nico Icecream 共同努力&#xff0c;打造了一個令我們特別自豪的流暢的沉浸式網站。 這個網站是專為 ONLYON Tourism 和會議而建&#xff0c;旨在展示里昂最具標志性的活動場所。觀看簡短的介紹視頻后&#xff0c;用戶…

Android 面試筆記整理-Binder機制

作者&#xff1a;浪人筆記 面試可能會問到的問題 從IPC的方式問到Binder的優勢為什么zygote跟其他服務進程的通訊不使用BinderBinder線程池和Binder機制 等等這些問題都是基于你對Binder的理解還有對其他IPC通訊的理解 IPC方式有多少種 傳統的IPC方式有Socket、共享內存、管道…

llvm-dyn_cast模板函數

dyn_cast dyn_cast是LLVM中用于執行安全的向下轉型&#xff08;downcasting&#xff09;的一個模板函數。在C中&#xff0c;向下轉型是將基類的指針或引用轉換為派生類的指針或引用。這種轉型在運行時進行&#xff0c;如果轉型失敗&#xff08;即&#xff0c;如果基類的對象實…

云計算虛擬仿真實訓平臺

一、云計算虛擬仿真系統概述 云計算虛擬仿真系統是一種基于云計算技術和虛擬化技術的系統&#xff0c;用于實現各種仿真和模擬任務。它可以提供強大的計算能力和資源管理&#xff0c;為用戶提供靈活、高效、可擴展的仿真環境。 該系統通常由一組服務器、網絡和存儲設備組成&am…

uniapp開發小程序-有分類和列表時,進入頁面默認選中第一個分類

一、效果&#xff1a; 如下圖所示&#xff0c;進入該頁面后&#xff0c;默認選中第一個分類&#xff0c;以及第一個分類下的列表數據。 二、代碼實現&#xff1a; 關鍵代碼&#xff1a; 進入頁面時&#xff0c;默認調用分類的接口&#xff0c;在分類接口里做判斷&#xff…

Linux c語言字節序

文章目錄 一、簡介二、大小端判斷2.1 聯合體2.2 指針2.3 網絡字節序 一、簡介 字節序&#xff08;Byte Order&#xff09;指的是在存儲和表示多字節數據類型&#xff08;如整數和浮點數&#xff09;時&#xff0c;字節的排列順序。常見的字節序有大端字節序&#xff08;Big En…

神經網絡基礎-神經網絡補充概念-08-邏輯回歸中的梯度下降算法

概念 邏輯回歸是一種用于分類問題的機器學習算法&#xff0c;而梯度下降是優化算法&#xff0c;用于更新模型參數以最小化損失函數。在邏輯回歸中&#xff0c;我們使用梯度下降算法來找到最優的模型參數&#xff0c;使得邏輯回歸模型能夠更好地擬合訓練數據。 邏輯回歸中的梯…

無監督學習之主成分分析-半導體制造高維數據如何降維

數據降維不只存在于半導體數據中&#xff0c;它是存在于各行各業的&#xff0c;我們要分析的數據維數較多的時候全部輸入維數較大這時就要采取降維的方法綜合出主要的幾列用于我們的分析。 PCA的哲學理念是要抓住問題的主要矛盾進行分析&#xff0c;是將多指標轉化為少數幾個…

前端技術棧es6+promise

let入門使用、 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>let 基本使用</title><script type"text/javascript">let name "hspedu教育";//老韓解讀//1. conso…

蘋果Mac像Windows一樣使用

一、將磁盤訪問設置的像Windows一樣&#xff1a; 1.1、點擊任務欄第一個按鈕打開“訪達”&#xff0c;點擊菜單欄上的訪達-偏好設置&#xff1a; 1.2、勾選“硬盤”&#xff0c;這樣macOS的桌面上就會顯示一個本地磁盤&#xff0c;之后重命名為磁盤根&#xff0c;相當于window…

SPF9139全力適配ios16與鴻蒙3.0,超實用數據提取、分析、恢復能力UP!

? 如今&#xff0c;群聊已成為人們必不可少的溝通窗口 家人群&#xff0c;好友群&#xff0c;班級群 粉絲群&#xff0c;交友群&#xff0c;工作群 …… 各類群聊鋪天蓋地般涌來的同時 也有一些群聊淪為了 賭博、傳播淫穢視頻、發表不當言論 等違法犯罪行為滋生之地 與…

mac 可以進行單片機(stm32)的開發嗎?

當涉及到在Mac上進行單片機開發時&#xff0c;是完全可行的。以下是為什么Mac適合單片機開發的解釋&#xff1a;開發工具&#xff1a;針對STM32單片機&#xff0c;你可以使用多種開發工具。一個常用的選擇是Segger Embedded Studio&#xff0c;它是一個功能強大的集成開發環境&…

ClickHouse(十八):Clickhouse Integration系列表引擎

進入正文前&#xff0c;感謝寶子們訂閱專題、點贊、評論、收藏&#xff01;關注IT貧道&#xff0c;獲取高質量博客內容&#xff01; &#x1f3e1;個人主頁&#xff1a;含各種IT體系技術&#xff0c;IT貧道_Apache Doris,大數據OLAP體系技術棧,Kerberos安全認證-CSDN博客 &…

IDEA常用設置與maven項目部署

目錄 前言 一、Idea是什么 二、Idea的優點 三、Idea的常用設置 主題設置 設置鼠標懸浮提示 忽略大小寫提示 自動導包 取消單行顯示Tabs 設置字體 配置類文檔注釋信息模版 設置文件編碼 設置自動編譯 水平或者垂直顯示代碼 快捷方式改成eclipse 設置默認瀏覽器…

Java并發編程(六)線程池[Executor體系]

概述 在處理大量任務時,重復利用線程可以提高程序執行效率,因此線程池應運而生。 它是一種重用線程的機制,可以有效降低內存資源消耗提高響應速度。當任務到達時&#xff0c;任務可以不需要的等到線程創建就能立即執行線程池可以幫助我們更好地管理線程的生命周期和資源使用,…

Jmeter - 函數助手

目錄 __StringFromFile __CSVRead __counter __RandomString __StringFromFile StringFromFile函數用于獲取文本文件的值&#xff0c;一次讀取一行 1、輸入文件的全路徑&#xff1a;填入文件路徑 2、存儲結果的變量名&#xff08;可選&#xff09; 3、Start file sequence …