2011-05-12 75 views
1

我正在根据HTTP服务器上的示例构建一个HTTP客户端,在boost website处给出。现在,该代码和我的区别在于,该示例使用服务器构造函数来启动异步操作。这是有道理的,因为服务器应该一直听。另一方面,在我的客户端中,我想先构造对象,然后有一个send()函数,该函数从连接到端点开始,然后发送请求并最终收听答复。这也有道理,不是吗?使用boost :: asio时出现的参考问题(我猜)

当我创建我的对象(客户端)时,我以与服务器示例(winmain.cpp)相同的方式执行此操作。它看起来像这样:

client c("www.boost.org); 
c.start(); // starts the io_service in a thread 
c.send(msg_); 

代码的相关部分是这些:

void enabler::send(common::geomessage& msg_) 
{ 
    new_connection_.reset(new connection(io_service_, 
     connection_manager_, 
     message_manager_, msg_ 
    )); 

    boost::asio::ip::tcp::resolver resolver(io_service_); 
    boost::asio::ip::tcp::resolver::query query(host_address, "http"); 

    resolver.async_resolve(query, boost::bind(
     &enabler::handle_resolve, 
     boost::ref(*this), 
     boost::asio::placeholders::error, 
     boost::asio::placeholders::iterator 
    )); 
} 

void enabler::run() 
{ 
    io_service_.run(); 
} 

这样做的问题是,该方案被卡住这里的某个地方。最后打印的是“解决主机”,然后程序结束。我不知道为什么,因为io_service应该阻塞,直到所有的异步操作都返回到它们的回调。但是,如果我改变我称呼功能的顺序,它就会起作用。如果我在拨打async_resolve()之后拨打run(),并且在我的主程序中省略了拨打电话start(),它就可以工作!

在这种情况下,io_service块,因为它应该,我可以看到,我从服务器得到响应。

这与我从同一班级呼叫run()这一事实有关,因为我呼叫async_resolve()。这是真的吗?我想当我打电话给run()时,我需要从主程序中提供一个参考,是这样吗?

我一直在努力获得io_service::work工作,但程序只是卡住了,是的,类似的问题,发生上述情况。所以它并没有真正的帮助。

那么,我能做些什么才能做到这一点?正如我前面所说的,我想要的是能够创建客户端对象,并让io_service始终在客户端类中的单独线程中运行。其次有一个功能,send(),发送请求到服务器。

回答

0

如果你不希望在任何时候都有一些工作,为了保持io_service繁忙,你应该在某个范围内构建一个io_service::work对象,可以退出而不必io_service::run()必须先返回。如果你在一个单独的线程中运行io_service,我会想象你不会有这个问题。

用这些代码片断很难知道你想要做什么。我想你会想沿着这些路线做点什么:

struct client 
{ 
    io_service io_service_; 
    io_service::work* w_; 
    pthread_t main_thread_; 
    client(): w_(new io_service::work(io_service)) { ... } 
    void start() { pthread_create(&main_thread_, 0, main_thread, this); } 
    static long main_thread(void* arg) { ((client*)arg)->io_service_.run(); } 
    // release the io_service and allow run() to return 
    void stop() { delete w_; w_ = 0; pthread_join(main_thread_); } 
}; 
2

您需要在致电run()之前至少开始一些工作,因为它在没有其他工作要做时会返回。

如果您在启动异步解决方案之前调用它,它将不会有任何工作,因此它将返回。

+0

谢谢,至少解释了一些。我可以在async_resolve()之后的函数send()中调用run()。但问题是,如果run()已被调用,则再次调用它将是错误的。您看到我想使用send(),以便在当前运行()完成之前发送请求。有没有办法确定io_service是否已完成,从而确定再次调用run是否安全?如果这能起作用,那将是好事,因为那样我就可以有一个if语句来检查它。 – 2011-05-12 18:12:46

+0

这听起来像你真的可以使用的是让run()无限期地走,所以你不必担心它? asio文档有一个[部分只是为此](http://www.boost.org/doc/libs/1_46_1/doc/html/boost_asio/reference/io_service.html#boost_asio.reference.io_service.stopping_the_io_service_from_running_out_of_work)。 – 2011-05-12 18:39:00

+0

是的!那正是我想要的!但是我已经阅读过你提到的那个页面,而且我不能用ioservice :: work来获取这个东西......我有一个定义为客户类的私有变量的io_service。在我的run()函数中,我试过这个: boost :: asio :: io_service :: work work(io_service_); io_service_.run(); 然后停止整个事情我应该调用io_service_.stop();那是对的吗?因为我可以'让它起作用 – 2011-05-12 18:48:07

相关问题