標籤:send 阻塞 線程阻塞 ems tail 資料包 eth0 組播 模式
編寫一個轉寄模組,雖然沒有要求一轉多時要達到多少路(不採用組播的情況下,單純的一路轉成多路),但是本著物盡其用的原則,儘可能測試一下極限。
網路環境:1000M,直連,多網卡
系統:Linux version 3.19.0
接收模式:udp模式的raw socket(最佳化的話,可以直接通過網卡處理)
發送模式:udp模式的raw socket(最佳化的話,可以直接通過網卡處理),單線程/多線程
2M 1轉N
裝置A ----------------> 轉寄裝置 ----------------> 裝置B
但N大到一定程度時,發現發送丟包。
注意,是轉寄裝置發送丟包,不是裝置B接收丟包。
裝置B接收丟包是可以理解的,畢竟2M碼率本身的突發性相當高,1轉N時,這個突發率更加擴大。
但是發送丟包是一個什麼情況,sendto的傳回值都進行了判斷,如果異常是會出現列印資訊的,但是沒有異常出現。
上網查資料。其中最靠譜的是
http://www.cnblogs.com/mengyan/archive/2012/10/04/2711340.html
1.發送頻率過高導致丟包
很多人會不理解發送速度過快為什麼會產生丟包,原因就是UDP的SendTo不會造成線程阻塞,也就是說,UDP的SentTo不會像TCP中的SendTo那樣,直到資料完全發送才會return回調用函數,它不保證當執行下一條語句時資料是否被發送。(SendTo方法是非同步)這樣,如果要發送的資料過多或者過大,那麼在緩衝區滿的那個瞬間要發送的報文就很有可能被丟失。至於對“過快”的解釋,作者這樣說:“A few packets a second are not an issue; hundreds or thousands may be an issue.”(一秒鐘幾個資料包不算什麼,但是一秒鐘成百上千的資料包就不好辦了)。
發送方丟包:內部緩衝區(internal buffers)已滿,並且發送速度過快(即發送兩個報文之間的間隔過短);
但是更讓人鬱悶的事情出現了。無論是網上資料,還是詢問同事,與tcp不同,發送這一塊沒有緩衝區啊。
問題的,已經設定SO_SNDBUF為64M,修改系統值為128M,設定後擷取到的SO_SNDBUF為128M。
現在就是在此種情況下發送丟包,128M是什麼概念啊,所以基本可以排除這一塊的問題。
通過命令watch netstat -s,可以明確的看出 Ip 項下的 outgoing packets dropped 持續增長,也就意味著確實是發送丟包。
然後就通過outgoing packets dropped ,sendto頻率過快等等關鍵詞開始查資料,結果讓人藍瘦香菇啊
陰差陽錯的情況下,查到了 IOCTLS
http://blog.csdn.net/wl_haanel/article/details/5305159
SIOCGIFTXQLEN , SIOCSIFTXQLEN
使用 ifr_qlen 讀取 或 設定 裝置的 傳輸隊列長度. 設定 傳輸隊列長度 是 特權操作.
於是通過
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));
if (-1 == ioctl(sock_, SIOCGIFTXQLEN, &ifr))
PLOG(ERROR) << "failed to get dev eth0 queue length";
LOG(KEY) << "Dev eth0 queue length " << ifr.ifr_qlen;
擷取到eth0上的隊列長度為1000,設定成10000試試
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));
ifr.ifr_qlen = 10000;
if (-1 == ioctl(sock_, SIOCSIFTXQLEN, &ifr))
PLOG(ERROR) << "failed to set dev eth0 queue length";
if (-1 == ioctl(sock_, SIOCGIFTXQLEN, &ifr))
PLOG(ERROR) << "failed to get dev eth0 queue length";
LOG(KEY) << "Dev eth0 queue length " << ifr.ifr_qlen;
果然,發現好了,沒有發送丟包了
去掉SO_SNDBUF的設定,擷取下SO_SNDBUF,才多少K,再測試,仍然沒有發送丟包。
結論:
sendto過快導致發送丟包,是因為發送隊列滿了,如果說緩衝區,估計大部分人都將誤解。
至於接收方因為突發率導致接收丟包的問題,那麼就要在發送方進行發送平滑進行解決。
sendto頻率過快導致發送丟包