读写超时

时间:2013-05-01 16:49:27

标签: c++ boost tcp boost-asio

如果需要花费一定的时间,我一直在寻找一种取消Boost ASIO读或写操作的方法。我的服务器正在发送HTTP请求,并从这些请求中读取结果,因此我最初将其编码为同步读/写,如果花了这么长时间,我只会继续并在它们返回时忽略结果。如果服务器出现故障,我的服务器将打开许多套接字,并且会崩溃,这会导致问题。所以我决定如果有太长的延迟我想取消读/写,但显然同步读/写不能在不破坏它们运行的​​线程的情况下被取消,这是我不想做的。所以我发现了一篇关于如何模仿异步调用的同步读/写并在超时时取消调用的帖子。 This 是我跟随的帖子。我知道这篇文章相当陈旧,所以我不确定函数调用是否会因为该版本和我正在使用的函数(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通常会如何处理。

1 个答案:

答案 0 :(得分: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()成员函数可以解决此问题,请参阅the documentation

  

说明

     

接收操作可能无法接收所有请求的号码   字节。如果需要确保,请考虑使用async_read功能   在异步之前接收所请求的数据量   操作完成。