Boost.Asio deadline_timer未按预期工作

Boost.Asio deadline_timer not working as expected

本文关键字:工作 timer Asio deadline Boost      更新时间:2023-10-16

我正试图在TCP套接字上实现Boost.Asio读取的超时。

我正在尝试将async_read_somedeadline_timer一起使用。下面的函数是一个类的成员,该类持有指向TCP套接字和io_service的智能指针。当在不返回任何数据的活动套接字上调用时,我期望发生的情况是等待2秒并返回false

结果是:如果套接字从不返回任何数据,那么它将按预期工作。如果服务器返回数据,那么对下面方法的继续调用会立即返回,因为对计时器的回调是在不等待两秒钟的情况下调用的。

我尝试注释掉async_read_some调用,该函数始终按预期工作。为什么async_read_some会改变计时器的工作方式?

    client::client() {
        // Init socket and timer
        pSock = boost::shared_ptr<tcp::socket > (new tcp::socket(io_service));
    }
bool client::getData() {
              // Reset io_service
                io_service.reset(); 
                // Init read timer
                boost::asio::deadline_timer timer(pSock->io_service());
                timer.expires_from_now(boost::posix_time::seconds(2)); 
                timer.async_wait(boost::bind(&client::read_timeout, this, boost::system::error_code(), true));

    //            // Async read the data
                pSock->async_read_some(boost::asio::buffer(buffer_),
                        boost::bind(&client::read_complete,
                        this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred
                        ));

                // While io_service runs check read result 
                while (pSock->io_service().run_one()) {
                    if (m_read_result > 0) {
                        // Read success 
                        return m_read_result;
                    }else if(m_read_result < 0){
                        return false;
                    }
                }
            }
}

void client::read_complete(const boost::system::error_code& error, size_t bytes_transferred) {
    if (!error) {
        m_read_result = bytes_transferred;
    }else{
        m_read_result = -1;
    }
}
void client::read_timeout(const boost::system::error_code& error, bool timeout) {
    if(!error){
        m_read_result = -1;
    }
}

设置计时器boost::system::error_code()时的简单问题应更改为_1或错误::占位符

timer.async_wait(boost::bind(&client::read_timeout, this, _1, true));

当您检查连接错误时,您已经否定了条件。

应该是:

if(error){
    std::cout  << "read_timeout Error - " << error.message() << std::endl;
}

现在您将看到,回调被调用,错误代码为boost::asio::error::operation_aborted

这是因为,当您接收到任何数据时,您会从函数getData返回,而deadline_timer的析构函数会调用带有错误代码集的回调。