2016-07-26 75 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中啓動的任何異步任務。

相關問題