2016-09-22 179 views
0

我目前正在使用boost :: asio :: io_service使用異步休息客戶端。 我試圖讓客戶端作爲更大程序的某種服務。 這個想法是,客戶端將執行異步http請求到一個休息API,獨立於運行主程序的線程。所以在客戶端內部會有另一個線程等待請求發送。 要通過請求客戶端我使用的是io_service對象io_service對象::工作io_service對象初始化。我幾乎重用了本教程給出的示例 - logger_service.hpp。 我的問題是,當它們在示例中將工作發佈到服務時,被調用的處理程序是一個簡單的函數。在爲我作出異步調用像這樣我的情況 (我已經做了必要的運行以下對象的所有instancies有的更在某種程度上能夠建立網絡連接):升壓異步休息客戶端

boost::asio::io_service io_service_; 
boost::asio::io_service::work work_(io_service_); //to prevent the io_service::run() to return when there is no more work to do 
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_(io_service_); 

在主程序我做以下電話:

client.Connect(); 
... 
client.Send(); 
client.Send(); 
... 

某些客戶端的僞代碼:

void MyClass::Send() 
{ 
... 
io_service_.post(boost::bind(&MyClass::AsyncSend, this); 
... 
} 


void MyClass::AsyncSend() 
{ 
... 
boost::io_service::asio::async_write(socket, streamOutBuffer, boost::bind(&MyClass::handle_send, this)); 
... 
} 

void MyClass::handle_send() 
{ 
boost::io_service::asio::async_read(socket, streamInBuffer, boost::bind(&MyClass::handle_read, this)); 
} 

void MyClass::handle_read() 
{ 
// ....treatment for the received data... 
    if(allDataIsReceived)  
     FireAnEvent(ReceivedData); 
    else 
    boost::io_service::asio::async_read(socket, streamInBuffer, boost::bind(&MyClass::handle_read, this)); 
} 

由於它的文檔中描述''方法請求io_service調用給定的處理程序和立即返回。我的問題是,嵌套的處理程序,例如AsyncSend中的:: handle_send,在使用post()後立即調用(當http響應已準備就緒時)?或者處理程序將以與post()調用順序定義的順序不同的順序調用? 我問這個問題,因爲當我只打一次客戶端 - >發送()客戶端似乎「工作正常」。但是當我連續進行2次調用時,如上例所示,客戶端無法完成第一次調用,而是執行第二次調用,並且在最後一些混亂執行後,2次操作失敗。

有沒有什麼辦法來做我所描述的執行完整的異步鏈,然後執行另一個。

我希望,我跟我的描述:)

+0

你可以讓它同步或添加一個條件變量來檢查前面的調用是否完成。 (假設你正確處理SSL連接) – Blacktempel

回答

0

你好Blacktempel不夠清晰,

感謝您給定的意見和想法,但是但是我工作的這要求使用異步調用的項目。 事實上,由於我是新手,提升了我的問題,我給出的例子在'handle_read'函數中是不正確的。現在我在示例中添加幾行,以更清楚地知道我處於什麼樣的狀態。 事實上,在很多例子中,可能都是他們,誰在處理主題如何創建一個異步客戶端是非常基本的...他們只是展示瞭如何鏈接不同的處理程序和數據處理時,'handle_read'是所謂的總是類似於「在屏幕上打印一些數據」,在這個相同的讀取處理程序內部。我認爲,與現實世界的問題相比,這是完全錯誤的! 沒有人會打印數據並完成她的程序執行......!通常一旦收到數據,就有另一種處理需要開始,例如FireAnEvent()。受不好的例子影響,我在讀取處理程序中完成了這個'FireAnEvent',顯然這是完全錯誤的!這樣做是不好的,因爲做這樣的事情,「handle_read」可能永遠不會退出或退出。如果這個處理程序沒有完成,那麼io_service循環也不會完成。如果您的進一步處理再次要求您的異步客戶端執行某些操作,則會啓動/重新啓動(我不確定詳細信息)io_service循環。在我的情況下,我以這種方式對異步客戶端進行了多次調用。最後,我看到了io_service是如何開始的,但從未結束。即使整個治療結束後,我從來沒有看到io_service停止。 所以最後我讓我的異步客戶端用handle_read中的接收數據填充一些全局變量,而不是直接調用另一個像FireAnEvent這樣的函數。我在io_service.run()之後移動了這個函數的調用(FireAnEvent)。它的工作原理是在run()方法結束後,我知道循環完成了! 我希望我的回答能幫助人們:)