首頁 > 軟體

boost.asio框架系列之buffer函數

2022-06-18 18:01:43

建立buffer

在io操作中,對資料的讀寫大都是在一個緩衝區上進行的,在asio框架中,可以通過asio::buffer函數建立一個緩衝區來提供資料的讀寫。buffer函數本身並不申請記憶體,只是提供了一個對現有記憶體的封裝。

char d1[128];
size_t bytes_transferred = sock.receive(asio::buffer(d1));

直接用字串做buffer也是常見的形式:

string str = " hello world " ;
size_t bytes_transferred = sock.send(asio::buffer(str));

除了這些基礎型別外,也可以使用stl中的容器,非常方便。

asio::buffer(std::vector<char>(128));
asio::buffer(std::array<char,128>());

將buffer還原為資料物件

前面的操作是通過把資料物件封裝成buffer,在使用過程中往往也需要把buffer還原為資料物件。

char* p1 = asio::buffer_cast<char*>(buffer);

獲取buffer大小

可以通過buffer_size函數獲取buffer大小。

size_t s1 = asio::buffer_size(buf);

讀寫buffer

讀寫buffer一般都是和io物件相關聯的,io物件成員函數中就提供了讀寫操作。以tcp::socket物件為例,它提供了read_some和write_some來實現讀寫操作:

std::array<char, 128> buf;
sock.read_some(asio::buffer(buf));

另外,asio名稱空間下也提供了通用的read、write函數,通過它們可以實現更加高階的讀寫功能

size_t bytes_transfered = asio::read(sock, asio::buffer(buf), asio::transfer_all(), err);

這裡我就使用了transfer_all標記強制讀滿buffer才返回,另外還有兩個比較常用的標記transfer_at_least()和transfer_exactly(),非常方便。

streambuf

asio::streambuf則是提供了一個流型別的buffer,它自身是能申請記憶體的。它的好處是可以通過stl的stream相關函數實現緩衝區操作,處理起來更加方便。

    //通過streambuf傳送資料
    asio::streambuf b;
    std::ostream os(&b);
    os << "Hello, World!n";

    size_t n = sock.send(b.data());    // try sending some data in input sequence
    b.consume(n); // sent data is removed from input sequence

 

    //通過streambuf讀資料
    asio::streambuf b;
    asio::streambuf::mutable_buffers_type bufs = b.prepare(512);    // reserve 512 bytes in output sequence
    size_t n = sock.receive(bufs);
    b.commit(n);    // received data is "committed" from output sequence to input sequence

    std::istream is(&b);
    std::string s;
    is >> s;

另外,asio名稱空間下還提供了一個的read_until函數,可以實現讀到滿足指定條件的字串為止,對於解析協定來說非常有用。

size_t n = asio::read_until(sock, stream, 'n');
asio::streambuf::const_buffers_type bufs = sb.data();
std::string line(asio::buffers_begin(bufs), asio::buffers_begin(bufs) + n);

這個指定條件除了是字串外,還可以是正規表示式,非常給力。這也是asio庫為什麼要依賴於boost.regex的原因。(雖然regex已經標準化了,但仍得使用boost.regex庫。等什麼時候asio也標準化後估計就可以直接使用std.regex庫了)

自定義記憶體分配

非同步IO操作時往往會申請動態記憶體,使用完後就釋放掉;在IO密集型的場景中,頻繁的申請釋放記憶體對效能會有較大影響。為了避免這個問題,asio提供了一個記憶體池式的模型 asio_handler_allocate 和 asio_handler_deallocate 來複用記憶體。

到此這篇關於boost.asio框架系列之buffer函數的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com