我什么时候调用boost :: asio :: streambuf :: consume()和boost :: asio :: streambuf :: commit()?

时间:2014-12-05 22:41:10

标签: c++ boost boost-asio iostream

我试图理解boost::asio::streambuf::consume()boost::asio::streambuf::commit()来电。在文档中,我们有示例,

boost::asio::streambuf b;
std::ostream os(&b);
os << "Hello, World!\n";

// try sending some data in input sequence
size_t n = sock.send(b.data());

b.consume(n); // sent data is removed from input sequence

boost::asio::streambuf b;

// reserve 512 bytes in output sequence
boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512);

size_t n = sock.receive(bufs);

// received data is "committed" from output sequence to input sequence
b.commit(n);

std::istream is(&b);
std::string s;
is >> s;

我理解这两个调用就像我理解文档中有关它们的内容一样 - 调用consume()boost::asio::streambuf内的输入序列中删除字符,然后调用commit()移动从boost::asio::streambuf的输出序列到其输入序列的字符。很公平。

我什么时候实际调用这些?查看boost::asio::read_until()来源,我们有

template <typename SyncReadStream, typename Allocator>
std::size_t read_until(SyncReadStream& s,
    boost::asio::basic_streambuf<Allocator>& b, char delim,
    boost::system::error_code& ec)
{
  std::size_t search_position = 0;
  for (;;)
  {
    // Determine the range of the data to be searched.
    typedef typename boost::asio::basic_streambuf<
      Allocator>::const_buffers_type const_buffers_type;
    typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
    const_buffers_type buffers = b.data();
    iterator begin = iterator::begin(buffers);
    iterator start_pos = begin + search_position;
    iterator end = iterator::end(buffers);

    // Look for a match.
    iterator iter = std::find(start_pos, end, delim);
    if (iter != end)
    {
      // Found a match. We're done.
      ec = boost::system::error_code();
      return iter - begin + 1;
    }
    else
    {
      // No match. Next search can start with the new data.
      search_position = end - begin;
    }

    // Check if buffer is full.
    if (b.size() == b.max_size())
    {
      ec = error::not_found;
      return 0;
    }

    // Need more data.
    std::size_t bytes_to_read = read_size_helper(b, 65536);
    b.commit(s.read_some(b.prepare(bytes_to_read), ec));
    if (ec)
      return 0;
  }
}

您可以看到,正如文档所述,boost::asio::read_until()是根据SyncReadStream&#39; s read_some()实现的。

对我来说,那就是

  1. SyncReadStream::read_some()不会致电boost::asio::streambuf::commit()
  2. boost::asio::read_until()致电boost::asio::streambuf::commit()
  3. 这些似乎都没有记录在案[ - {1}}的文档中,也没有记录在boost::asio::read_until()的文档中。
  4. 我不知道我是否应该打电话给SyncReadStream
  5. 使用我的同步代码我似乎不需要它,而不是在我调用自由函数boost::asio::streambuf::commit()boost::asio::read()时。我在处理程序中的异步代码中使用它主要是因为我使用的示例有它,但我也不确定是否也可以调用它。当我尝试使用boost::asio::read_until() boost::asio::streambufstringstream时,std::string似乎没有发挥作用 - 没有在commit()上调用commit(),就不会停止或停止任何操作。

    任何人都可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:4)

Asio定义了一些接受asio::streambuf的{​​{3}},他们关注preparecommit

另一方面,如果您要asio::streambuf使用auxiliary free functions (read_xxx)接受lower-level functions的型号,则必须致电streambuf::prepare(),返回符合MutableBufferSequence概念的对象,将此对象作为缓冲区传递,并在函数填充后调用commit()。

在这两种情况下,在您从n读取streambuf个字节的数据后,您必须调用consume(n) - 才能使用输入序列。

答案 1 :(得分:1)

read_until在其实施中使用read_some。因此,read_some调用streambuf::commitread_until不会(直接)。

通常您不需要调用commitconsume,但如果您想对缓冲区数据执行某些操作 - 这可以是一种方法。例如,如果您使用二进制协议,则无法使用read_until正确检查。