簡體   English   中英

使用自定義streambuf和boost :: asio異步操作

[英]Using custom streambuf with boost::asio async operations

我正在使用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), ...);

是否可以使用自定義std::streambufboost::asio::basic_streambuf包裝Sink ,以便它可以處理向其寫入數據部分?

對於對象被傳遞作為參數緩沖器 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() 然后,使用中間緩沖區調用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 );

確保根據您所需的邏輯檢查並處理錯誤

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM