Boost ASIO の読み取りまたは書き込み操作に一定の時間がかかる場合にキャンセルする方法を探していました。私のサーバーは HTTP リクエストを送信し、それらのリクエストから結果を読み取っています。そのため、もともとは同期読み取り/書き込みとしてコーディングしていました。時間がかかる場合は、処理を続行して、返された結果を無視していました。これにより、サーバーがダウンした場合に問題が発生し、サーバーが多くのソケットに対して開かれ、クラッシュしました。そのため、遅延が長すぎる場合は読み取り/書き込みをキャンセルすることにしましたが、実行中のスレッドを破棄せずに同期読み取り/書き込みをキャンセルできないようです。これはやりたくありません。そこで、非同期呼び出しで同期読み取り/書き込みを模倣し、タイムアウト時に呼び出しをキャンセルする方法に関する投稿を見つけました。 これ 私がフォローした投稿です。この投稿はかなり古いことを知っているので、そのバージョンと私が使用しているバージョン (1.48) 以降に関数呼び出しが変更されたかどうかはわかりませんが、これは正しく機能していないようです。これが私のコードです
bool connection::query_rtb(const std::string &request_information, std::string &reply_information)
{
try
{
boost::optional<boost::system::error_code> timer1_result, timer2_result, write_result, read_result;
boost::array<char,8192> buf;
buf.assign(0);
boost::asio::deadline_timer dt(io_service_);
dt.expires_from_now(boost::posix_time::milliseconds(100));
dt.async_wait(boost::bind(&connection::set_result, this, &timer1_result, _1, "timer1"));
boost::asio::async_write(socket_, boost::asio::buffer(request_information, request_information.size()), boost::bind(&connection::set_result, this, &write_result, _1, "write"));
io_service_.reset();
while(io_service_.run_one())
{
if(write_result)
{
dt.cancel();
}
else if(timer1_result)
{
socket_.cancel();
}
}
boost::asio::deadline_timer dt2(io_service_);
dt2.expires_from_now(boost::posix_time::milliseconds(3000));
dt2.async_wait(boost::bind(&connection::set_result, this, &timer2_result, _1, "timer2"));
boost::asio::async_read(socket_, boost::asio::buffer(buf), boost::bind(&connection::set_result, this, &read_result, _1, "read"));
//socket_.async_receive(boost::asio::buffer(buf), boost::bind(&connection::set_result, this, &read_result, _1, "read"));
io_service_.reset();
while(io_service_.run_one())
{
if(read_result)
{
dt2.cancel();
}
if(timer2_result)
{
socket_.cancel();
}
}
reply_information = buf.data();
std::cout << reply_information << std::endl;
return true;
}catch(std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
void persistent_connection::set_result(boost::optional<boost::system::error_code> *a, boost::system::error_code ec, std::string t)
{
std::cout << t << std::endl;
a->reset(ec);
}
誰かがこのコードに何か問題があるのか 、またはなぜそれが機能しないのかについて何か考えがあるのだろうかと思っていました. 現在、書き込みは問題ないようですが、タイマーで dt2 が完了するまで読み取りは行われません。さらに情報が必要な場合はお知らせください。喜んで提供させていただきます。
編集:
以前にテストしたと思っていたものをテストして、うまくいったようです。async_receive
代わりに使用すると、async_read
私が抱えていた問題が解決したようです。なぜこれが私の問題を引き起こすのでしょうか? 私の論理に問題があるのか、それともasync_read
通常はそのように行動するのかを知りたい.