クライアントから送信されたリクエストを処理する、 boost asio ドキュメント(シングルスレッド サーバー)の HTTP サーバーの例から大きく影響を受けた、単純な非同期サーバーがあります。
私server
のクラスは、connection
新しいクライアントが接続してそのメソッドを呼び出すたびに新しいオブジェクトを作成しstart()
ます (HTTP サーバーの例のように)。インスタンスはクライアントのリクエストを読み取り、その後非同期操作 (つまりと)connection
を使用して応答を送信します。boost::asio::async_read
boost::asio::async_write
connection
クラスの簡略化されたバージョンは次のとおりです。
void connection::start() {
// Read request from a client
boost::asio::mutable_buffers_1 read_buffer = boost::asio::buffer(
buffer_data_, REQUET_SIZE);
boost::asio::async_read(socket_, read_buffer,
boost::bind(&connection::handle_read_request, shared_from_this(),
read_buffer, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
// Error handling omitted for the sake of brievty
void connection::handle_read_request(boost::asio::mutable_buffers_1& buffer,
const boost::system::error_code& e, std::size_t bytes_transferred) {
request req = parse_request(buffer);
if(req.type_ = REQUEST_TYPE_1) {
reply rep(...........);
rep.prepare_buffer(buffer_data_.c_array());
// Send the request using async_write
boost::asio::async_write(socket_,
boost::asio::buffer(buffer_data_, rep.required_buffer_size()),
boost::bind(&connection::stop, shared_from_this()));
} else if(req.type_ = REQUEST_TYPE_2 {
// Need to do heavy computational task
}
}
これらはすべて非常にうまく機能しますが、場合によっては、重い計算タスクを実行する必要があります ( REQUEST_TYPE_2
)。これらのタスクはhandle_read_request
、シングルスレッド サーバーをブロックし、他のクライアントがサービスを開始できなくなるため、自分では実行できません。
理想的には、負荷の高い計算タスクをスレッド プールに送信し、connection::handle_done_task(std::string computation_result)
タスクの完了時に接続クラスのメソッド (例: ) を実行したいと考えています。これhandle_done_task(std::string computation_result)
により、計算の結果がクライアントに送信されます ( を使用boost::asio::async_write
)。
どうすればそれができますか?注意すべき問題がいくつかありますか (boost::asio::async_write
複数のスレッドから同じソケットで呼び出しても安全ですか)?