7

我似乎无法很好地解释 consumer() 和 commit() 的真正含义,实际上我根本不了解 streambuf。

我的理解是streambuf只是一个字符数组。但是为什么在文档中,

basic_streambuf::data
Get a list of buffers that represents the input sequence.

所以实际上有很多缓冲区?什么是“输入序列”和“输出序列”?这是另外两个缓冲区吗?

下面的代码究竟做了什么?

streambuf b;
size_t size;
size = read( socket, b.prepare( 1024 ) ); 
b.commit( size );
size = write( socket, b.data() );
b.consume( size );

当我调用 b.prepare() 时,它是否为 read() 分配了一个新缓冲区来放置数据?那么数据何时从该缓冲区传输到底层的 streambuf 缓冲区?我以为是commit(),但是

basic_streambuf::commit
Move characters from the output sequence to the input sequence.

所以看起来提交实际上将数据从“输出序列”移动到“输入序列”,而没有提及用于存储数据的底层缓冲区!

4

1 回答 1

7

Boost ASIO streambuf 不仅仅是一个字符数组。从 basic_streambuf 文档中:

basic_streambuf 类派生自 std::streambuf 以将 streambuf 的输入和输出序列与一个或多个字符数组相关联。这些字符数组在 basic_streambuf 对象的内部,但提供了对数组元素的直接访问,以允许将它们有效地用于 I/O 操作。写入 basic_streambuf 对象的输出序列的字符将附加到同一对象的输入序列。

该文档继续讨论可能的实施策略。streambuf 对象可以简单地使用带有指针的单个连续字符数组来管理输入和输出序列。但是该接口允许更复杂的方案。

您询问了代码片段实际上做了什么,但这取决于底层实现。简而言之,prepare() 确保底层缓冲区足够大以容纳您尝试放入其中的内容。它还使您可以通过 mutuable_buffers 对象访问缓冲区。一旦数据被写入 streambuf(大概是在调用读取处理程序时),commit() 使该数据可用于输入序列。您可以使用 data() 访问这些字节。在你完成缓冲区中的数据后(因为你复制了它,处理了它,或者其他什么),consume() 从输入序列中删除数据。对 data() 的后续调用将不包含上一次调用的字节。

您还断言从未提及用于存储数据的底层缓冲区,这是正确的。由 ASIO 作者决定如何存储实际数据。

于 2014-12-04T20:52:03.023 回答