2017-04-19 24 views
0

我正在開發一個應用程序,通過UDP(1036字節數據報大小)接收高達900 Mb/s的數據。在「正常」環境下(沒有系統負載和用戶交互),一切正常:操作系統或應用程序不報告丟棄的數據報。當我開始點擊Windows資源管理器的文件夾樹時,更改其主顯示窗格的內容時,數據報將被刪除。我通過使用Windows性能監視器並檢查數據報有效負載中烘焙的序列號來觀察此情況。 對於每次點擊,都會丟失數百個數據報。操作Windows資源管理器窗口時UDP數據包丟失

接收緩衝區大小增加(128 MB操作系統,甚至更多用於我的應用程序)。我進一步觀察到,如果調用

ioctlsocket(my_socket, FIONREAD, &readableBytes); 

返回精確的字節數,則沒有緩衝區達到其極限。最高觀察值低於2 MB。 我不確定哪些其他緩衝區可能會溢出以及如何跟蹤其狀態。

該應用程序是使用Qt開發的。除了UDP接收線程之外,還有三個線程正在使用中。當沒有用戶交互並且接收線程被切斷時,它們都是空閒的。所有這些都是重現問題的每個測試設置的情況。

接收線程的第一次迭代使用Qt UDP套接字,並檢查正確的序列號。

第二次迭代使用普通的WinSock調用recv(...),檢查另一個線程完成的序列號。這顯然增加了線程數量。這兩個線程都通過一個無鎖隊列進行通信,這個隊列完全能夠處理呈現給它的讀寫操作。儘管如此,即使只有接收者線程正在運行(讀取數據報並丟棄它們),也可以觀察到與上述相同的行爲。

即使是具有多個接收者線程的實現(也只能讀取和丟棄)顯示相同的行爲。

即使數據速率下降到330 Mb/s,但仍然不太頻繁,可能會出現問題。它以更低的數據速率消失。

是的我知道UDP不能保證傳送,但數據包明顯到達我的機器,並被充足的CPU時間和緩衝區空間丟棄 - 這似乎很奇怪,至少可以說。

我想知道:

  1. 是否有此行爲的任何解釋?
  2. 如果是這樣,有什麼可能的解決方案?
  3. 如果沒有,可以通過檢查找出導致此問題的原因?

任何幫助或方向遵循將不勝感激,謝謝!

回答

2

簡單的解釋是,你嚴重滯後於傳入的流。價值2MB的緩衝數據是巨大的當你有1kb數據包! UDP旨在爲您提供當前的數據,而不是陳舊的數據,而當您實時處理2000個數據包時,網絡堆棧會做它應該做的事情並開始丟棄數據包。這完全是預期的。你也許應該有幾十個數據包,最糟糕的情況是數千個。

您將不得不重寫代碼以使用分佈在多個高優先級線程上的現代重疊I/O,理想情況下使用直接由網絡堆棧填充的無複製數據包緩衝區。

Qt可以在抽象這個方面做得更好,但是直到有人實現它,你所能做的最好的事情就是閱讀關於Windows的現代高性能網絡並自己完成工作。

+0

UDP可用於任何數據,而不僅僅是_current data_。例如,洪流協議使用它進行傳輸,根據定義,它沒有_current data_。 –

+0

我可能循環地使用「current」來表示那些並不比最近到達的數據包差。假設是數據包以固定速率到達。如果是這樣,接收緩衝區填充顯然是由於接收代碼無法應付數據速率。保留這些數據包沒有意義,隊列只會增長,所以它們必須被丟棄。 2MB在千兆位鏈路上的值爲22ms。 –

+0

感謝您的回答!我假設你的意思是在重疊的I/O模式下使用WSARecv。 –

相關問題