2012-05-16 58 views
6

我正在用boost的asio庫編寫服務器。服務器使用一組Connection對象(一個圍繞boost :: asio :: tcp :: socket的包裝類)處理許多併發連接。在Connection類中,使用socket.async_read_some(...)不斷讀取套接字,並且每當使用新數據調用讀處理程序時,會立即再次調用socket.async_read_some()以供更多數據讀取。boost :: asio :: tcp :: socket關閉並取消沒有處理程序被調用

現在,服務器可能會因爲某種原因決定斷開一個客戶端,所以自然要做的是調用connection.close(),然後調用socket.close(),這會導致所有掛起的異步操作被取消。這會導致使用boost :: asio :: error :: operation_aborted調用讀取處理程序(綁定到類Connection中的方法)。我的問題是:我不希望發生這種情況。

socket.close()之後,我想摧毀插座和連接,然後從活動客戶端的服務器的列表中刪除它的指針。然而,直到io_service.run()的下一次迭代纔會調用讀處理程序,這意味着我不能立即銷燬套接字或已傳遞給socket.async_read_some()的讀處理程序,直到處理程序被調用錯誤。所以我不得不推遲那些對象的銷燬;這很煩人。

有沒有一種安全的方式要麼

  • 取消未決異步操作沒有任何處理程序被調用,這樣我就可以放心地socket.close後立即銷燬插座(),或
  • 到安全地知道什麼時候沒有更多的處理程序可能被稱爲

或者我完全接近這個錯誤的方式嗎?

回答

4

當async.operation完成 - 無論是successfuly或錯誤 - 它的完成處理程序被調用。這是重要的保證,我不認爲嘗試「破解」這種行爲是個好主意。 在你的用例中遇到的問題通常通過使用shared_ptr(shared_from_this idiom):綁定shared_ptr<Connection>來處理,當你得到operation_aborted(或其他錯誤)時不要發出另一個async_read,這樣當所有的處理程序Connection對象被它的套接字銷燬。

+0

這聽起來很不錯。我確定不要使用shared_ptr,甚至不知道enable_shared_from_this。我曾經這樣做過:「socket.async_connect(endpoint,boost :: bind(&Connection :: done_connect,this,_1))」,所以現在我只需在綁定調用中添加一個額外的「shared_from_this()」並更新方法簽名爲一個額外的shared_ptr,即使實際的shared_ptr甚至不會在處理程序中使用?即shared_ptr就在那裏以保證對象仍然存在。聽起來不錯? – jlh

+0

至少我這樣實現它,現在它工作得很好。非常感謝你! – jlh

+0

@jlh,說shared_ptr「不會在處理程序中使用」是不正確的。如果將成員函數綁定到shared_ptr,它將存儲在綁定器(使用bind()創建的函子)中,並在函子調用中取消引用。結果,只要該仿函數存在,指針就會一直存在。 –

相關問題