2012-02-04 83 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; 
} 
相关问题