udp丟包原因分析

什麼會導致udp丟包呢,這裏列舉了如下幾點原因:

  1. 調用recv方法接收端收到數據後,處理數據花了一些時間,處理完後再次調用recv方法,在這二次調用間隔裏,發過來的包可能丟失。對於這種情況可以修改接收端,將包接收後存入一個緩衝區,然後迅速返回繼續recv。

  2. 發送的包巨大丟包。雖然send方法會幫你做大包切割成小包發送的事情,但包太大也不行。例如超過30K的一個udp包,不切割直接通過send方法發送也會導致這個包丟失。這種情況需要切割成小包再逐個send。

  3. 發送的包較大,超過mtu size數倍,幾個大的udp包可能會超過接收者的緩衝,導致丟包。這種情況可以設置socket接收緩衝。以前遇到過這種問題,我把接收緩衝設置成64K就解決了。
    int nRecvBuf=321024;//設置爲32K
    setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char
    )&nRecvBuf,sizeof(int));

  4. 發送的包頻率太快,雖然每個包的大小都小於mtu size 但是頻率太快,例如40多個mut size的包連續發送中間不sleep,也有可能導致丟包。這種情況也有時可以通過設置socket接收緩衝解決,但有時解決不了。

  5. 發送的廣播包或組播包在windws和linux下都接收正常,而arm上接收出現丟包。這個還不好解決,我的解決方法是大包切割成大小爲1448的小包發送,每個包之間sleep 1毫秒,雖然笨,但有效。我這裏mtu size爲1500字節,減去udp包頭8個字節,減去傳輸層幾十個字節,實際數據位1448字節。(*_mem單位爲頁,4KB,其他選項爲字節,見ip-sysctl.txt )
    除此之外還可以試試設置arm操作系統緩衝:

# 設置mtu size 1500最大
ifconfig eth0 mtu 1500
# 查看接收緩衝最大和默認大小。
sysctl -A | grep rmem
# 設置接收緩衝的最大大小
sysctl -w net.core.rmem_max=1048576
sysctl -w net.core.rmem_default=1048576
sysctl -w net.ipv4.udp_mem=1048576
sysctl -w net.ipv4.udp_rmem_min=1048576
  1. 局域網內不丟包,公網上丟包。這個問題我也是通過切割小包並sleep發送解決的。如果流量太大,這個辦法也不靈了。

總之udp丟包總是會有的,如果上述方法解決不了,還有這個幾個方法:

  • 要麼減小流量
  • 要麼換tcp協議傳輸
  • 麼做丟包重傳的工作

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章