2011-05-16 120 views
2

我想使用boost asio創建一個http客戶端。爲了進行結構化和優化,我研究了boost asio的示例,以瞭解一個好的實現應該是什麼樣的。啓動boost時的例程:: asio :: io_service

大多數情況下,我遵循HTTP Server的結構,所以我有一個連接管理器,它擁有一組指向每個單獨連接的指針。現在,這裏的大不同的是,已經在server.cpp的構造異步函數被調用,即

 
acceptor_.async_accept(new_connection_->socket(), 
     boost::bind(&server::handle_accept, this, 
     boost::asio::placeholders::error)); 

,並在io_service對象是通過函數調用服務器啓動winmain.cpp ::運行( ):

 
io_service_.run(); 

在我的實現,因爲它是一個客戶端,而不是服務器,我想等待用戶調用的send()函數之前,我開始連接到服務器。因此,我已將所有連接到服務器的函數調用移入連接類。當用戶請求到MSG發送到以下稱爲服務器:

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

我想開始在一個單獨的線程每一個連接對象,這真的是我的問題的背景。我該怎麼做才能獲得結構化和優化的代碼?

我試過了,例如HTTP Server 2的例子,設置一個io_services的線程池並分配工作給他們,這樣他們纔會返回,直到停止。這似乎是一個好主意,因爲我會讓io服務始終在後臺運行。因此,我從我相當於server.cpp啓動線程池,在一個線程:

 
boost::thread t(boost::bind(&geocast::enabler::io_service_pool::run, &io_service_pool_)); 

,但是從我自己的試驗和錯誤分析,似乎之前,你已發出異步函數無法啓動io_service對象, 真的嗎?因爲我的程序卡住了。在我的情況下,我只想在用戶意味着發送POST請求或GET請求時調用async_resolve。支持我的理論; Chat Client首先調用一個async_connect並以async_read作爲回調,這樣他們就可以在創建客戶端之後安全地調用io_service.run()。我不希望從服務器讀取所有時間,只是爲了能夠啓動io_service,因爲這不是普通客戶端的工作方式,對吧?如果瀏覽器沒有從用戶導航到網站的每個可能的服務器上讀取數據......

如果我不使用示例2中的線程池,而是在單獨的類中啓動每個連接類,每個擁有自己的io_service,一切正常。但是,使用簡單的循環程序來選擇合適的io_service的線程池看起來非常有吸引力。對於我來說,多線程的最佳方法是什麼?我只是挑剔,應該堅持一個連接一個io_service的東西?

回答

1

我都試過了,作爲HTTP服務器2 例如,設立的 io_services一個線程池,分配工作給他們 ,使他們不會返回,直到 停止。

當使用異步編程,我強烈建議您使用以下設計順序:

  1. io_service與單個線程的線程
  2. 池調用一個io_service
  3. io_service每線程或其他奇特的設計

你應該只如果在分析之後,您的當前設計證明是一個瓶頸,那麼請轉到下一個設計。

,但是從我自己的嘗試和錯誤 分析,似乎之前,你必須出具 異步函數無法啓動 io_service對象,是真的嗎?

你是正確的,io_service::run()documentation法術這一點很清楚

的run()函數阻塞,直到所有 工作已經完成,並且沒有 更多的處理程序被分派,或 直到io_service已停止。

防止io_service::run()立即返回正確的方法是要排隊的一些處理,或者實例化一個io_service::workobject,並保持它的範圍,只要你想run()保持活躍。

+0

感謝您的好評!關於io_service :: run():我的意思是「無法啓動io_service BEFORE」是這樣的:我首先創建一個客戶端對象,它有一個在線程中運行的函數。之後,我調用客戶端類中的send()函數。現在,這變得棘手。在客戶端類中,調用async_resolve()。同時,在主線程中,io_service以run()方式啓動,即在主線程中首先調用send()函數,然後調用io_service.run()。但該計劃只是卡住了。爲什麼?看起來工作()沒有幫助... – 2011-05-18 13:22:05

+0

@Thomas問一個新問題,根據評論我不清楚你想要完成什麼。 – 2011-05-18 16:19:29

1

使用ASIO時,您將放棄對ASIO的程序流控制。如果將代碼更改爲使用線程池,則可以共享控制權,並且請致電run_one()而不是run()。 run_one()僅將一個IO作業分派給線程,因此如果在ioservice中有多個事件,則必須多次調用run_one()。

你有沒有想過產生一個新的線程作爲你的老闆線程,然後讓你的老闆線程創建一堆工作線程?你的老闆線程可以調用run(),然後你的UI線程可以調用post()來發送一個新的工作單元。除了不必手動調用和調度ioservice中的任務,它還會使清理和關閉更直接,因爲當調用run()時,您的老闆線程會阻塞。

相關問題