2012-02-04 122 views
3

有沒有辦法從streambuf中讀取而不刪除字節?如何從Boost ASIO streambuf讀取?

我正在從緩衝區中讀取'消息大小'字段以檢查是否收到了整個消息。

如果不是,我發佈另一個異步讀取以獲取它,但處理程序然後無法知道消息應該多長時間 - 因爲大小字段已被刪除。

任何幫助表示讚賞!

E.g.

boost::asio::streambuf _buffer; 

void onReceive(const boost::system::error_code& e, std::size_t bytesTransferred) 
{ 
    if(e) return; 

    if(_buffer.size() > 0) 
    { 
    // Partial message was previously received, but I don't know how long. 
    } 
    else 
    { 
    _buffer.commit(bytesTransferred); 

    /* Read the size (and remove it from the stream) */ 
    unsigned short size = 0; 
    std::istream in(&_buffer); 
    in.read((char*)&size, sizeof(unsigned short); 

    /* Got the whole message? */ 
    if(_buffer.size() > size) 
    { 
     /* Yes. */ 
    } 
    else 
    { 
     /* No - read the rest. */ 
     boost::asio::async_read(/*...*/); 
    } 
    } 
} 

回答

2

您可以使用read_async啓動使用郵件標頭的大小讀取,然後在「完成情況」回調調整它,就像這樣:

typedef boost::system::error_code error_code; 

template <typename Stream, typename Message> 
void MessageReader<Stream, Message>::startRead() 
{ 
    readBuffer = allocateMsg(); 
    async_read(stream, 
      boost::asio::buffer(readBuffer.get(), sizeof(*readBuffer)), 
      boost::bind(&MessageReader<Stream, Message>::bytesToRead, this, 
         boost::asio::placeholders::error, 
         boost::asio::placeholders::bytes_transferred), 
      boost::bind(&MessageReader<Stream, Message>::readDone, this, 
         boost::asio::placeholders::error, 
         boost::asio::placeholders::bytes_transferred)); 
} 

template <typename Stream, typename Message> 
size_t MessageReader<Stream, Message>::bytesToRead(const error_code& error, 
                size_t bytes_read) 
{ 
    size_t result; 

    if (error) 
    result = 0;           // error - stop reading 

    else if (bytes_read < sizeof(CmnMessageHeader)) 
    result = sizeof(CmnMessageHeader) - bytes_read;  // read rest of header 

    else if (readBuffer->header.byteCount > sizeof(*readBuffer)) 
    result = 0;           // bad byte count 

    else 
    result = readBuffer->header.byteCount - bytes_read; // read message body 

    return result; 
} 

template <typename Stream, typename Message> 
void MessageReader<Stream, Message>::readDone(const error_code& error, 
               size_t bytes_read) 
{ 
    if (error) 
    { 
    if (error.value() == boost::system::errc::no_such_file_or_directory) 
    { 
     notifyStop(); 
    } 

    else if (error.value() != boost::system::errc::operation_canceled) 
    { 
     notifyStop(); 
    } 

    // else the operation was cancelled, thus no stop notification is needed and 
    // we can merely return 
    } 

    else if (bytes_read != readBuffer->header.byteCount) 
    { 
    LOG4CXX_ERROR(logger, "Message byte count mismatch"); 
    notifyStop(); 
    } 

    else 
    { 
    handleMsg(readBuffer); 
    startRead(); 
    } 
} 

編輯:添加的typedef ERROR_CODE。

+0

輝煌,謝謝。 – James 2012-02-05 17:48:42

0

有您可以採取兩種方法:

  1. 問題單讀閱讀的大小字節數(比如4),這個問題對於所需大小的讀取。

  2. 使用讀取一些調用,並緩衝你的代碼中的字節,說一個向量,然後進行分析。

我會選擇2,它的意思是複製緩衝區,但我會冒險,它比多個閱讀一些電話便宜。

+0

謝謝,我已經採取了你的意見。 – James 2012-02-05 17:48:32

1

我昨天做了這個。所以我想我會提供我的解決方案...

#include <iostream> 
#include <sstream> 
#include <algorithm> 
#include <iterator> 

#include <boost/asio.hpp> 
#include <boost/asio/streambuf.hpp> 

void ReadFromStreambuf() 
{ 
    boost::asio::streambuf mybuffer; 

    // write some data to the buffer 
    std::ostream o2buffer (&mybuffer); 
    o2buffer << "hello stackoverflow"; 

    // get buffer size 
    size_t nBufferSize = boost::asio::buffer_size(mybuffer.data()); 

    // get const buffer 
    std::stringstream ssOut; 
    boost::asio::streambuf::const_buffers_type constBuffer = mybuffer.data(); 

    // copy const buffer to stringstream, then output 
    std::copy(
     boost::asio::buffers_begin(constBuffer), 
     boost::asio::buffers_begin(constBuffer) + nBufferSize, 
     std::ostream_iterator<char>(ssOut) 
    ); 

    std::cout << ssOut.str() << "\n"; 
} 


int main(int argc, char const *argv[]) 
{ 
    ReadFromStreambuf(); 
    return 0; 
} 
相關問題