对于对象作为缓冲器参数被传递为async_read()
,所述缓冲器参数之一:
因此,可以在发生阅读时编写一个与Sink
对象交互的自定义类。但是,boost::asio::basic_streambuf
看起来并不是用作基类的。
如果Sink::write
只是对底层内存的抽象,请考虑使用类似于basic_streambuf::prepare()
的方法,其中成员函数返回给定大小的缓冲区的句柄。底层的内存实现仍然会在mutable_buffer
之后被抽象化。例如:
boost::asio::async_read(socket, sink.buffer(size), ...);
如果Sink::write
具有业务逻辑,诸如执行逻辑基于某些字节的值分支,那么它可能需要一个中间缓冲器传递给async_read()
。然后用async_read()
的处理程序调用Sink::write()
中间缓冲区。例如:
void handle_read_into_sink(boost::system::error_code error,
std::size_t bytes_transferred,
boost::asio::ip::tcp::socket& socket,
Sink& sink,
char* buffer,
std::size_t buffer_size,
std::size_t bytes_remaining,
boost::function< void() > on_finish)
{
sink.write(buffer, buffer_size);
bytes_remaining -= bytes_transferred;
// If there are more bytes remaining, then continue reading.
if (bytes_remaining)
{
read_into_sink(socket, sink, buffer, buffer_size,
bytes_remaining, on_finish);
}
// Otherwise, all data has been read.
else
{
on_finish();
}
}
void read_into_sink(boost::asio::ip::tcp::socket& socket,
Sink& sink,
char* buffer,
std::size_t buffer_size,
std::size_t bytes_remaining,
boost::function< void() > on_finish)
{
boost::asio::async_read(
socket, boost::asio::buffer(buffer , buffer_size),
boost::asio::transfer_exactly(buffer_size),
boost::bind(handle_read_into_sink,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
boost::ref(socket),
boost::ref(sink),
buffer,
buffer_size,
bytes_remaining,
on_finish));
}
,并开始与异步读循环:
read_into_sink(socket, sink, small_buffer, sizeof_small_buffer,
total_stream_size, read_handler_callback);
确保检查和处理根据您所需要的逻辑错误。
感谢您的快速响应。我的'Sink :: write()'没有任何bussines逻辑。问题是我无法为整个流分配内存。我希望能够分配小缓冲区,并在溢出时将数据传递给'Sink :: write()'。这样,一个boost :: asio :: async_read()会根据需要执行尽可能多的Sink :: write(),然后调用ReadHandler。我没有看到'MuttableBufferSequence'版本如何实现这一点。 – Daszek
我可能不了解溢出的上下文,但是从它的声音中可以看出,它可以通过读取少量数据的async_read循环来解决,写入接收器并继续读取,直到处理完已知的流大小。一旦整个流被处理完毕,它就会调用所需的'ReadHandler'。我的答案的最后部分已被修改,以证明这一点。 –