3

boost::asio を使用してサーバー アプリケーションを作成しています。
ユーザーから既知の量のデータを読み取り、次の API を持つデータ シンクに書き込みます。

class Sink {
    ...
    void write(const char *data, size_t size);
}

データは大きく、write(..)1 つのストリームを処理するために複数回呼び出すことができます。
私のコードでは、次のように呼び出したいと思います:

boost::asio::async_read(socket, sink_buffer,
    boost::asio::transfer_exactly(size), ...);

Sinkカスタムでラップすることは可能ですstd::streambufboost::asio::basic_streambuf、それともデータ部分の書き込みを処理できますか?

4

1 に答える 1

1

のbuffers引数として渡されるオブジェクトの場合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 );

必要なロジックに基づいてエラーをチェックして処理してください。

于 2012-06-20T16:07:17.467 に答える