2011-05-12 62 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