【发布时间】: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,它在你调用run或poll之前就被销毁了。尝试在main中创建它,然后将其传递给MyClass::create,然后在其上调用run()。 -
@kenba 显然你是对的,但我也忘记了我的 io_service 上的 reset(),我会尽量让他活着
-
@PsykoBabar 您是否打算在
read()中再次致电io_service::run?要让io_service保持活力,请按照@kenba 的建议进行操作,但也可以从connect_handler调用read()。这样在连接成功后会调用read()。现在,无论是否有连接,都会调用read()。我知道这可能是调试代码,您没有从read()中的套接字读取,但您绝对不需要reset和io_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