1

我一直在寻找一种方法来取消 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通常的行为方式。

4

1 回答 1

1
boost::array<char,8192> buf;

...

boost::asio::async_read(socket_, boost::asio::buffer(buf), boost::bind(&connection::set_result, this, &read_result, _1, "read"));

您已指示您的程序从套接字读取 8192 个字节。如果将逻辑从使用async_read()自由函数切换到async_receive()成员函数可以解决此问题,请查阅文档

评论

接收操作可能不会接收到所有请求的字节数。async_read如果您需要确保在异步操作完成之前接收到请求的数据量,请考虑使用该函数。

于 2013-05-02T14:45:39.887 回答