2013-03-08 73 views
1

我寫監聽網絡上的插座和線路收到的數據包分離守護程序網關服務。我打算使用boost asio,但我堅持幾個問題。以下是我計劃實現的服務器的設計:添加一個套接字描述符到io_service對象動態和消除它

  1. 網關將使用boost asio偵聽TCP連接。

  2. 網關還將使用boost asio偵聽來自守護程序的流式Unix域連接。

  3. 每當tcp連接上有數據包時,網關就會查看數據包中的協議標記,並將數據包放在服務將要偵聽的unix域連接上。

  4. 每當服務連接上有一個數據包時,網關就會查看客戶端標籤並將其放在相應的客戶端連接上。

網關中的每個描述符都將是一個NONBLOCKING。

當網關正在寫入服務連接時,如果服務套接字已滿,有可能會收到EAGAIN或EWOULDBLOCK錯誤,但我遇到了一個特定問題。我計劃通過排隊緩衝區並「等待服務連接準備寫入」來解決這個問題。

如果我要使用select系統調用「等待服務連接準備寫入」,將轉化爲在writefd列表中添加fd並將其傳遞給select。一旦服務連接準備好寫入,我將把入隊的緩衝區寫入連接,並從select的writefdlist中刪除服務連接。

我怎麼做升壓ASIO是一回事嗎?這樣的事情可能嗎?

回答

1

如果您想使用該方法,請使用boost::asio::null_buffers啓用Reactor-Style operations。此外,通過socket::non_blocking()成員函數將Boost.Asio套接字設置爲非阻塞。該選項將設置同步套接字操作爲非阻塞狀態。這與將本地套接字設置爲非阻塞不同,因爲Boost.Asio將本地套接字設置爲非阻塞,並模擬同步操作的阻塞。

但是,如果Proactor樣式操作是一個選項,那麼請考慮使用它們,因爲它允許應用程序忽略某些較低級別的細節。當使用proactor風格操作時,Boost.Asio將代表應用程序執行I/O,正確處理EWOULDBLOCK,EAGAINERROR_RETRY邏輯。例如,當Boost.Asio發生前面提到的錯誤之一時,它將I/O操作推回到其內部隊列中,推遲重新嘗試,從而允許嘗試其他操作。

很多時候,有需要使用反應堆風格的操作,而不是前攝樣式的操作的兩個約束:

  • 另一個庫的預期,進行I/O操作本身。
  • 內存限制。使用前攝器時,緩衝區的生命週期必須超過讀取或寫入操作的持續時間,併發操作可能需要自己的緩衝區。當數據準備好被讀取時,Reactor允許緩衝區的生命週期開始,當數據不再被使用時結束。
+0

+1好的總結或爲什麼反應堆模式可能是必要的原因 – 2013-03-12 02:41:36

1

使用boost :: asio,你不需要混淆非阻塞模式和/或返回代碼,如EAGAIN EWOULDBLOCK等。另外,你不是「向套接字循環添加套接字」或類似的東西;這是隱藏給你的,因爲它更高級的框架。

典型模式是

  1. 創建io_service對象
  2. 你用結合到插座上io_service對象
  3. 創建某些異步事件(async_connect,async_read,ASYNC_WRITE或等等)創建套接字。
  4. 您運行io_service對象::運行或類似的方法調度。
  5. 當時間到了,asio會觸發你的處理程序。

在boost :: asio頁面查看examples。我認爲async echo server可以說明你的任務的技巧。

+0

我同意,我不應該關心EAGAIN或EWOULDBLOCK多數民衆贊成什麼asio是正確的,但wouldnt的write_handler將連續調用,因爲套接字將始終準備好寫?在我的情況下,此處的服務連接將始終準備好寫入並導致繁忙的循環。 – 2013-03-08 06:06:37

+0

@RavikumarTulugu no。處理程序將在作業完成或完全失敗時被調用(例如取消或同行斷開連接)。調用write_handler之後,asio將會忘記它,因爲寫入作業已完成。當你需要寫下一個數據塊時,你需要再次調用async_write。所以,處理程序不會在你寫入時被調用,它在你的任務結束時被調用。 – PSIAlt 2013-03-08 06:10:02

0

如果多個線程將寫入用於連接的同一個套接字對象,那麼您需要使用互斥鎖(或使用Windows的關鍵部分)單線程代碼。

至於 - 「當網關寫入服務連接時,如果服務套接字已滿,就有可能發生EAGAIN或EWOULDBLOCK錯誤」,我相信ASIO在內部爲您處理,因此您不需要不得不擔心它。

相關問題