<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    boost.asio系列――buffer

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    創建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也值得一試。

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全