2017-08-07 59 views
1

使用獨立asio,我使用read_some實現了一個服務器。我的服務器循環會從套接字中累積所有收到的數據。下面的精簡代碼不能正常工作,但我可以通過將inbuf.prepare()語句移入循環來修復它。asio streambuf可變緩衝區類型 - 如何使用prepare()

asio::streambuf inbuf; 
asio::streambuf::mutable_buffers_type inbufs = inbuf.prepare(4096); 
while(connected) 
{ 
    asio::error_code ec; 
    size_t bytes_read = Socket().read_some(inbufs,ec); 
    inbuf.commit(bytes_read); 
    std::string s = std::string(asio::buffers_begin(inbufs), 
      asio::buffers_begin(inbufs) + inbuf.size()); 
    inbuf.consume(bytes_read); 
} 

當製備()是環路和讀由於連接用4096邊界建立的雜交的總字節數之外,字符串s只會有數據到該邊界。換句話說,s將比bytes_read短。我推測如果我想在循環之外保留prepare(),我需要像下面這樣的消耗循環,但是這也不起作用。

asio::streambuf inbuf; 
asio::streambuf::mutable_buffers_type inbufs = inbuf.prepare(4096); 
while(connected) 
{ 
    asio::error_code ec; 
    size_t bytes_read = Socket().read_some(inbufs,ec); 
    while(bytes_read > 0) 
    { 
     inbuf.commit(bytes_read); 
     std::string s = std::string(asio::buffers_begin(inbufs), 
      asio::buffers_begin(inbufs) + inbuf.size()); 
     inbuf.consume(inbuf.size()); 
     bytes_read -= s.size(); 
    } 
} 

任何人都可以澄清prepare()的作用,爲什麼需要重複調​​用它?

回答

1

streambuf實現爲具有自定義分配器的std::vector<char>prepare只是分配請求的內存量。它不需要被調用一次以上。

爲了保存所有接收到的數據,你只需將蓄電池主循環外:

std::string accumulated_data; 
while (connected) { 
    ... 
    accumulated_data.append(
     boost::asio::buffers_begin(inbufs), 
     boost::asio::buffers_begin(inbufs) + bytes_read); 
    ... 
} 

警告:這取決於頻率的總數,這可能變得非常低效的「追加」由於內存分配和移動/副本。但由於我不知道你想要處理的數據,這是我能想到的最好的。

+0

在我的情況下,我可以估計在讀取第一個數據塊後預期的總數據大小,因此我可以調用cumulative_data.reserve()以避免頻率存儲器重新分配。 – edj

0

Asio :: buffer是一個容器。 欲瞭解更多詳細信息,請訪問here

當asio :: buffer被調用時,OS和Complier不知道應該爲它分配多少內存。所以buffer.prepare(/ * Memory Size * /)被稱爲成員函數來提供該空間。

總是建議您應該分配一定大小的內存緩衝區,如果沒有收到或傳輸的數據可能會出現亂碼。

相關問題