2016-07-26 111 views
1

我最近遇到了boost :: asio异步任务的问题。我想返回一个指向侦听端口的对象的指针。 它适用于我使用socket.read_some方法,但此方法阻止我的主,我希望我的MyClass :: create方法返回。Boost Asio - 为什么我的异步操作无法启动?

所以我尝试了一个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; 
} 
+0

由于您正在'MyClass :: create'中创建一个临时的'boost :: asio :: io_service',在你可以调用'run'或'poll'之前它被销毁了。尝试在'main'中创建它,然后将它传递给'MyClass :: create',然后调用'run()'。 – kenba

+0

@kenba显然你是对的,但我也忘了我的io_service重置(),我会尽量让他活着 – PsykoBabar

+0

@PsykoBabar是你在'read()'中再次调用'io_service :: run'的意图' ?为了保持'io_service'活着,请按照@kenba的建议,但是也可以从'connect_handler'调用'read()'。这样'read()'在连接成功之后被调用。现在,无论是否存在连接,都会调用read()。我知道这可能是调试代码,并且你不是从'read()'中的套接字读取的,但是你绝对不需要'重置''io_service'并再次调用'run'。 – aichao

回答

0

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

确实存在io_service在“create”方法之后被销毁的问题,所以返回的指针不能继续读取。 我不得不在一次调用run()来启动回调函数,但是我不能在main函数中执行它,因为我希望main函数继续做其他事情。

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

现在我调用了“create”返回一个指向MyClass的指针,它不停止在MyClass中启动的任何异步任务。

相关问题