boost.asio系列——buffer


創建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官方文檔示例,或者網上的這篇文章

就我個人而言,並不贊成在項目的前期就使用上這個allocator,畢竟這樣帶來了很大的代碼復雜度。而是作為一個性能優化點,在后期性能優化的時候再試試用它有沒有效果。並且內存池的也有很多不同的方案,google的google-perftools也值得一試。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM