有没有办法在不删除字节的情况下从 streambuf 中读取?
我正在从缓冲区读取“消息大小”字段以检查是否收到了整条消息。
如果不是,我将发布另一个异步读取以获取它,但处理程序无法知道消息应该有多长 - 因为大小字段已被删除。
感谢任何帮助!
例如
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(/*...*/);
}
}
}
最佳答案
您可以使用 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();
}
}
编辑:为 error_code 添加了 typedef。
关于c++ - 如何读取 Boost ASIO streambuf?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9144547/