【问题标题】:Boost Asio - Why do my asynchronous operations not launch?Boost Asio - 为什么我的异步操作没有启动?
【发布时间】:2016-11-29 17:27:47
【问题描述】:

我最近遇到了 boost::asio 异步任务的问题。我想在侦听端口的对象上返回一个指针。 当我使用 socket.read_some 方法时它可以工作,但是这个方法阻塞了我的 main 方法,我希望我的 MyClass::create 方法返回。

所以我尝试了 async_read 调用,但我看到在我的 read() 方法中,没有启动任何异步任务。我试图找出可能导致问题的原因,但没有找到解决此问题的方法。

这是我的代码,这里不是使用 async_read 而是使用 async_wait,出现同样的问题,计时器没有启动。

感谢您提供的任何帮助。

头文件:

#ifndef MYCLASS_HPP
#define MYCLASS_HPP

#include <memory>
#include <boost/asio.hpp>

class MyClass
{
public:
MyClass(boost::asio::io_service& ios);

void read();
void read_handler(const boost::system::error_code& error);

static std::shared_ptr<MyClass> create(std:: string const & host, uint16_t port);

bool connect (std::string const & host, uint16_t port);
void connect_handler(const boost::system::error_code& error);


boost::asio::ip::tcp::socket    m_socket;
bool                m_flag;
std::vector<uint8_t>        m_buffer;   
};

#endif

源文件:

#include "MyClass.hpp"

#include <boost/bind.hpp>

MyClass::MyClass(boost::asio::io_service& ios)
    :m_flag(false), m_socket(ios), m_buffer(20)
{   
}

void MyClass::read_handler(const boost::system::error_code& er)
{
    std::cout << "Timer waited 5 sec" << std::endl;
}


void MyClass::read()
{
    boost::asio::deadline_timer t(m_socket.get_io_service(),boost::posix_time::seconds(5));
    t.async_wait(boost::bind(&MyClass::read_handler,this,boost::asio::placeholders::error));
    m_socket.get_io_service().run();//Should make the io_service wait for all asynchronous tasks to finish
    std::cout << "This message should be displayed after the wait" << std::endl;
}

void MyClass::connect_handler(const boost::system::error_code& error)
{
    if(!error)
    {
        std::cout << "Connection done" << std::endl;
        m_flag = 1; 
    }
    else 
    {
        std::cout << "Error in connection: " << error.message() << std::endl;
    }
}


//connect method
bool MyClass::connect(std::string const & host, uint16_t port)
{
    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(host),port);

    m_socket.async_connect(endpoint, 
            boost::bind(&MyClass::connect_handler, this,
            boost::asio::placeholders::error));

    m_socket.get_io_service().run();//Wait async_connect and connect_handler to finish

    if (m_flag == 0) return false;
    else return true;
}


std::shared_ptr<MyClass> MyClass::create(std:: string const & host, uint16_t port)
{
    boost::asio::io_service ios;

    std::shared_ptr<MyClass> ptr(new MyClass(ios));

    bool bol = ptr->connect(host, port);
    ptr->read();

    //while(1){}

    if(bol == true)
    {
        //connection success, reading currently listening, pointer is returned to the user
        return ptr;
    }
    else
    {
        //connection failure, pointer is still returned to the user but not listening as he's not connected
        return ptr;
    }
}

还有我的主要:

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/asio.hpp>
#include "MyClass.hpp"

int main()
{
    try
    {
    std::cout << "Creation of instance" << std::endl;

    std::shared_ptr <MyClass> var = MyClass::create("127.0.0.1", 8301);

    std::cout << "Instance created" << std::endl;



    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

【问题讨论】:

  • 因为你在MyClass::create 中创建了一个临时的boost::asio::io_service,它在你调用runpoll 之前就被销毁了。尝试在main 中创建它,然后将其传递给MyClass::create,然后在其上调用run()
  • @kenba 显然你是对的,但我也忘记了我的 io_service 上的 reset(),我会尽量让他活着
  • @PsykoBabar 您是否打算在read() 中再次致电io_service::run?要让io_service 保持活力,请按照@kenba 的建议进行操作,但也可以从connect_handler 调用read()。这样在连接成功后会调用read()。现在,无论是否有连接,都会调用read()。我知道这可能是调试代码,您没有从read() 中的套接字读取,但您绝对不需要resetio_service 并再次调用run
  • 不,我不想在 read() 中调用 io_service::run,最后我的目标是在 main 中调用 MyClass::create 后保持 async_read() 活着(没有 io_service 主要)。不幸的是,@kenba 说的是真的,我必须找到另一种方法来保持我的 io_service 活着。我会在他对问题进行排序时将此主题标记为已解决
  • @PsykoBabar,@aichao 也是正确的。 io_service.run() 需要做一些工作来阻止它完成。您的MyClass::connect_handler 应该执行异步操作:写入、读取等以使其保持活动状态,

标签: c++ c++11 boost boost-asio shared-ptr


【解决方案1】:

我想出了如何解决我的问题。

我确实遇到了 io_service 在“create”方法后被销毁的问题,因此在 main 中返回的指针无法继续读取。 我不得不在某一时刻调用 run() 来启动回调,但我无法在 main 中执行此操作,因为我希望 main 继续做其他事情。

所以我创建了一个类来启动一个单独的线程并包含一个 io_service。该线程定期调用 run() 。然后将其作为属性添加到 MyClass。

现在我可以调用“create”返回指向 MyClass 的指针,该指针不会停止在 MyClass 中启动的任何异步任务。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多