編寫一個轉發模塊,雖然沒有要求一轉多時要達到多少路(不采用組播的情況下,單純的一路轉成多路),但是本着物盡其用的原則,盡可能測試一下極限。
網絡環境: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過快導致發送丟包,是因為發送隊列滿了,如果說緩存區,估計大部分人都將誤解。
至於接收方因為突發率導致接收丟包的問題,那么就要在發送方進行發送平滑進行解決。
