c++ - 如何读取 Boost ASIO streambuf?

标签 c++ boost boost-asio streambuf

有没有办法在不删除字节的情况下从 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/

相关文章:

c++ - LLVM 中间表示 : fptoui vs. fptosi

传递 container.start() 和 container.end() 的 C++ 更简洁的替代方法

c++ - boost::property_tree : 解析复杂的xml结构

c++ - asio 周期性定时器

c++ - 指向类成员作为模板参数的指针(具有以下类的类型)

c++ - std::is_assignable 是如何工作的?

c++ - 使用 decltype 返回元素类型的元函数

c++ - 输入流到 vector<char> - vector 迭代器不可取消引用

c++ - 在 Boost.Asio 中同时使用 SSL 套接字和非 SSL 套接字?

c++ - Boost Asio - 为什么我的异步操作没有启动?