2012-01-04 105 views
2

我已經創建了一個客戶端/服務器程序,客戶端啓動 一個Writer類的實例並且服務器啓動一個 Reader類的實例。然後寫入器將數據DATA_SIZE字節的數據 異步地寫入讀取器,每USLEEP毫秒。boost :: asio發送數據比通過TCP接收更快。或者如何禁用緩衝

只有在前一個請求的「正在寫入」處理程序調用了 時,寫入程序的每個連續async_write請求才會完成 。

的問題是,如果作家(客戶端)的寫入更多的數據到比閱讀器(服務器)的 插座能夠接收這似乎 是行爲:

  • 作家將啓動寫入(我認爲)系統緩衝區,甚至 雖然數據還沒有被讀者接收,它將是 調用「寫入」處理程序沒有錯誤。

  • 當緩衝區已滿時,boost :: asio不會再觸發「on write」 處理程序,直到緩衝區變小。

  • 與此同時,讀者仍然在接收數據的小塊 。

  • Writer程序關閉 後,Reader繼續接收字節的事實似乎證明了這個理論是正確的。

我需要做到的,是因爲 數據需要被「實時」,以防止這種緩衝(儘可能)。

我猜我需要使用的是 ASIO優惠,像no_delay或send_buffer_size,但我只是猜測 這裏我還沒有成功,這些試驗的套接字選項的某種組合。

我認爲人們可以想到的第一個解決方案是使用UDP而不是TCP來使用 。這將是這種情況,因爲我需要切換到 UDP由於其他原因,以及在不久的將來,但我會 第一想知道如何做到這一點與TCP只是爲了 的緣故吧直接在我的腦海中,以防將來有一天會出現類似的 問題。

NOTE1:在我開始在ASIO庫的異步操作的實驗我已經使用線程,鎖和ASIO ::插座來實現這一相同的情況下,在那個時候沒有經歷過這樣的緩衝。我不得不切換到異步API,因爲asio似乎不允許定時中斷同步調用。

NOTE2:這是一個工作示例演示該問題:http://pastie.org/3122025

編輯:我做了第二次檢查,在我NOTE1我提到我使用ASIO時:: iosockets我沒有經歷這種緩衝。所以我想確定並創建了這個測試:http://pastie.org/3125452事實證明,緩衝是有事件與asio :: iosockets,所以一定有別的東西,導致它順利,可能更低的FPS。

+0

聽起來像一個表現不佳的服務器或緩慢/擁塞/有故障的網絡。當我遇到這樣的問題時,我試圖通過在兩臺使用雙絞線(沒有路由器,沒有額外流量)連接的計算機上運行服務器和客戶端來分解問題,以查看會發生什麼。 – 2012-01-04 14:50:42

回答

2

由於大多數網絡應用程序的意圖是在主機之間傳輸數據,因此TCP/IP絕對適合最大化吞吐量。在這種情況下,預計N個字節的傳輸需要T秒,顯然,接收器處理數據的速度有點慢並不重要。事實上,正如你注意到TCP/IP協議實現了滑動窗口,它允許發送方緩衝一些數據,以便始終準備發送,但最終的節流控制權仍然留給接收方。接收器可以全速,自行調節或者暫停傳輸。

如果你不需要吞吐量,而是想保證發送者發送的數據儘可能接近實時,那麼你需要的是確保發送者不寫下一個包,直到他從接收方收到已處理先前數據包的確認。因此,不要盲目發送數據包,直到被阻止,而是定義一個消息結構,以便將控制消息從接收方發回給發送方。

顯然,使用這種方法,您的權衡是每個發送的數據包更接近發送者的實時數據,但是您限制了可以傳輸多少數據,同時略微增加了協議使用的總帶寬(即附加控制消息)。另外請記住,「接近實時」是相對的,因爲您仍然會面臨網絡延遲以及接收器處理數據的能力。所以你也可以看看你的特定應用程序的設計約束條件,以確定你真正需要的「接近」。

如果你需要非常接近,但同時你不關心數據包是否因爲舊數據包數據被新數據取代而丟失,那麼UDP/IP可能是更好的選擇。然而,a)如果你有可靠的交付需求,你可能會重新發明一部分tcp/ip的輪子,並且b)記住某些網絡(公司防火牆)傾向於阻止UDP/IP,同時允許TCP/IP通信和c )甚至UDP/IP也不會是實時的。

相關問題