Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
263 views
in Technique[技术] by (71.8m points)

c++ - Boost ASIO streambuf

I am confused about the input sequence and output sequence in boost asio::streambuf classes.

According to the code examples (for sending data) in the documentation it seems that the buffer representing the input sequence is used for writting to socket and the one representing the output sequence is used for reading.

Example -

boost::asio::streambuf b;
std::ostream os(&b);
os << "Hello, World!
";
// try sending some data in input sequence
size_t n = sock.send(b.data());
b.consume(n); // sent data is removed from input sequence

Now, is there a nomenclature problem?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The nomenclature for boost::asio::streambuf is similar to that of which is defined in the C++ standard, and used across various classes in the standard template library, wherein data is written to an output stream and data is read from an input stream. For example, one could use std::cout.put() to write to the output stream, and std::cin.get() to read from the input stream.

When manually controlling the streambuf input and output sequences, the general lifecycle of data is as follows:

  • Buffers get allocated with prepare() for the output sequence.
  • After data has been written into the output sequence's buffers, the data will be commit()ed. This committed data is removed from the output sequence and appended to the input sequence from which it can be read.
  • Data is read from the input sequence's buffers obtained via data().
  • Once data has been read, it can then be removed from the input sequence by consume().

When using Boost.Asio operations that operate on streambuf or stream objects that use a streambuf, such as std::ostream, the underlying input and output sequences will be properly managed. If a buffer is provided to an operation instead, such as passing passing prepare() to a read operation or data() to a write operation, then one must explicitly handle the commit() and consume().

Here is an annotated version of the example code which writes directly from an streambuf to a socket:

// The input and output sequence are empty.
boost::asio::streambuf b;
std::ostream os(&b);

// prepare() and write to the output sequence, then commit the written
// data to the input sequence.  The output sequence is empty and
// input sequence contains "Hello, World!
".
os << "Hello, World!
";

// Read from the input sequence, writing to the socket.  The input and
// output sequences remain unchanged.
size_t n = sock.send(b.data());

// Remove 'n' bytes from the input sequence. If the send operation sent
// the entire buffer, then the input sequence would be empty.
b.consume(n);

And here is the annotated example for reading from a socket directly into an streambuf. The annotations assume that the word "hello" has been received, but not yet read, on the socket:

boost::asio::streambuf b;

// prepare() 512 bytes for the output sequence.  The input sequence
// is empty.
auto bufs = b.prepare(512);

// Read from the socket, writing into the output sequence.  The
// input sequence is empty and the output sequence contains "hello".
size_t n = sock.receive(bufs);

// Remove 'n' (5) bytes from output sequence appending them to the
// input sequence.  The input sequence contains "hello" and the
// output sequence has 507 bytes.
b.commit(n);

// The input and output sequence remain unchanged.
std::istream is(&b);
std::string s;

// Read from the input sequence and consume the read data.  The string
// 's' contains "hello".  The input sequence is empty, the output
// sequence remains unchanged.
is >> s;

Note how in the above examples, the steam objects handled committed and consuming the streambuf's output and input sequences. However, when the buffers themselves were used (i.e. data() and prepare()), the code needed to explicitly handle commits and consumes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...