2016-11-22 87 views
0

我有我的udp接收器插座相當標準的設置。我的發送者以36Hz發送數據,接收器以72Hz讀取。每次發送12072個字節。C++ udp recvfrom減少下降

當我做貓/ proc/net/udp。我通常會得到

sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops 
7017: 0101007F:0035 00000000:0000 07 00000000:00000000 00:00000000 00000000  0  0 10636 2 0000000000000000 0   
7032: 00000000:0044 00000000:0000 07 00000000:00000000 00:00000000 00000000  0  0 14671 2 0000000000000000 0   
7595: 00000000:0277 00000000:0000 07 00000000:00000000 00:00000000 00000000  0  0 11113 2 0000000000000000 0   
7660: 00000000:22B8 00000000:0000 07 00000000:00004100 00:00000000 00000000 1000  0 251331 3 0000000000000000 352743 

你可以看到rx_queue在那裏有一些值,讀取速度不夠快?

我的代碼

int recv_len = recvfrom(s, buf, BUFLEN, MSG_TRUNC, (struct sockaddr *) &si_other, &slen); 
    // dont worry buflen is like 64000 no error here 

    std::cout <<" recv_len "<<recv_len<<std::endl; 

我總是得到輸出recv_len 12072即使隊列是相當大的?爲什麼是這樣 ?有沒有辦法加快我的閱讀或閱讀隊列中的所有消息?即使我的閱讀頻率較高,我也不明白什麼是錯誤的。

+0

也許您的代碼沒有按照您的想法做它在做什麼? (例如,你認爲你的閱讀是在72HZ,但你沒有,或者有一個簡單的bug,你沒有發現......等等) – nos

回答

0

UDP數據報總是作爲一個完整的原子單元傳播。如果您發送12072個UDP數據報,您的接收器將完全收到一個12072數據報或根本沒有任何數據報 - 您將永遠不會收到部分消息(*)或多個消息連接在一起。

請注意,使用此大小的數據報時,它們幾乎肯定在IP層被分割,因爲它們可能大於網絡的MTU(最大傳輸單元)。在這種情況下,如果沿途或接收主機丟棄任何一個分段或發現其中一個分段被損壞,則整個UDP數據報將被丟棄。

(*消息可以被截斷如果提供給recvfrom緩衝區太小,但它永遠不會甚至被認爲是用於接收如果整個郵件無法在內核中進行重組。)

如果你無法收到所有正在發送的消息,我會檢查你是否需要增加分配給UDP的內核緩衝區空間。這是通過sysctl實用程序完成的。具體而言,您應該檢查並可能調整net.core.rmem_maxnet.ipv4.udp_mem的值。請參見相應的文檔:
https://www.kernel.org/doc/Documentation/sysctl/net.txt
https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt

最後,似乎有點好奇地談論「讀頻率」 - 我認爲這意味着你是輪詢插座每秒72次?爲什麼不專用一個線程來讀取插座。然後該線程可以阻塞recvfrom,並且接收將以儘可能最小的延遲完成。 (在任何情況下,這都值得一試,即使僅用於測試 - 查看投票是否導致您無法跟上發件人。)

+0

是的,我也認爲在內核級別上發生了一些事情。專用1線程可以減少掉落數量,但不會顯着。但更重要的是它也減少了從發件人到我處理郵件的時間的延遲。我想我會研究udp_mem的大小,並與這些值一起玩。 – itsnevertoobadtoaskforhelp