我正在使用boost :: asio编写服务器应用程序 我正在从用户读取已知数量的数据并将其写入具有以下api的数据接收器:
class Sink {
...
void write(const char *data, size_t size);
}
数据很大,可以多次调用write(..)
来处理一个流
在我的代码中,我想打电话:
boost::asio::async_read(socket, sink_buffer,
boost::asio::transfer_exactly(size), ...);
是否可以使用自定义Sink
或std::streambuf
打包boost::asio::basic_streambuf
,以便它可以处理向其写入数据部分?
答案 0 :(得分:1)
对于作为async_read()
的 buffers 参数传递的对象,缓冲区参数:
MutableBufferSequence
要求的类型。boost::asio::basic_streambuf
对象。因此,可以在读取时编写与Sink
对象交互的自定义类。但是,boost::asio::basic_streambuf
似乎并不是设计用作基类。
如果Sink::write
只是底层内存的抽象,请考虑使用类似于basic_streambuf::prepare()
的方法,其中成员函数返回给定大小的缓冲区的句柄。底层内存实现仍将在mutable_buffer
后面抽象。例如:
boost::asio::async_read( socket, sink.buffer( size ), ... );
如果Sink::write
具有业务逻辑,例如基于某些字节的值执行逻辑分支,则可能需要将中间缓冲区传递给async_read()
。然后,使用中间缓冲区调用Sink::write()
将从async_read()
的处理程序中完成。例如:
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 );
确保根据您所需的逻辑检查并处理错误。