聲明:本文原內容來自
http://hi.baidu.com/roxws/blog/item/1f57e52eea0ddc5c4fc226ac.html
一、UDP發送緩衝區,接收緩衝區,這個主要預防是網路抖動。
1.
預設udp socket的緩衝區由net.core.rmem_default決定(沒有2倍等特殊關係),即rmem_default反映實際預設緩衝大小(注意不是rmem_max)
sk->sk_recbuf = sysctl_rmem_defaul;
sk->sk_sndbuf = sysctl_wmem_defaul;
2. net.core.rmem_default的配置不受net.core.rmem_max限制,實際效果也不受rmem_max限制,
rmem_max只用於限制setsockopt
3.
程式自己通過setsockopt設定SO_RCVBUF時,設定的實際效果值為參數*2,且要求參數不超過rmem_max(超過時用rmem_max)
4. wmem_*與上相同
查看更多的核心源碼,我們可以看到類似的情況也適用於SO_RCVBUF選項。如下面的一段摘錄的代碼:
427 case SO_RCVBUF:
428
432
433 if (val > sysctl_rmem_max)
434 val = sysctl_rmem_max;
435 set_rcvbuf:
436 sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
437
452 if ((val * 2) < SOCK_MIN_RCVBUF)
453 sk->sk_rcvbuf = SOCK_MIN_RCVBUF;
454 else
455 sk->sk_rcvbuf = val * 2;
456 break;
二、在設定rmem_default 同時,要設定txqueuelen。傳輸緩區長度大小。
rmem_default:是所有socket連接埠通用的。而通過
setsockopt 只設定當前連接埠。其實這個數字是表示一個連接埠上所有未發出的包所佔的空間,並非真是描述某個緩衝區的。
txqueuelen:是真是存在的一個緩衝區,是包在下行過程中,實際存在的一個緩衝區。
所以對txqueuelen的設定應該根據wmem大小增大,以保證使用wmem來控制發送緩衝區,以保證可以通過sendto失敗來監控到緩衝區滿的情況。txqueuelen > (wmem / (包大小 + 250)) * socket數, 如一個網卡僅有一個發送socket,設定wmem=1M, 將txqueuelen設定為1w設定方法:ifconfig eth1
txqueuelen 10000設定後立即生效,不需要重啟進程
三、tcp服務端設定
通用socket設定參看
http://hi.baidu.com/roxws/blog/item/e2958354bf32df58564e00c0.html
服務端要特別注意的是 time_wait問題。制定協議時,應該盡量讓用戶端先close。要注意:進程退出,tcp會主動發送結束符給對方。
#net.ipv4.tcp_tw_reuse = 1 對降低time_wait等待時間沒有用處。測試沒發現有什麼用。這個應該主要是預防重啟進程,提示連接埠已經被綁定的問題。
#net.ipv4.tcp_tw_recycle = 1 快速回收,降低time_wait等待時間。
設定socket的SO_LINGER選項:
這裡要注意,如果有重發,會導致用戶端增加重發次數。所以建議小心使用!!
此選項指定函數close對連線導向的協議如何操作(如TCP)。核心預設close操作是立即返回,如果有資料殘留在套介面緩衝區中則系統將試著將這些資料發送給對方。
SO_LINGER選項用來改變此預設設定。使用如下結構:
struct linger {
int l_onoff; /* 0 = off, nozero = on */
int l_linger; /* linger time */
};
有下列三種情況:
1、設定 l_onoff為0,則該選項關閉,l_linger的值被忽略,等於核心預設情況,close調用會立即返回給調用者,如果可能將會傳輸任何未發送的資料;
2、設定 l_onoff為非0,l_linger為0,則套介面關閉時TCP夭折串連,TCP將丟棄保留在套介面發送緩衝區中的任何資料並發送一個RST給對方,而不是通常的四分組終止序列,這避免了TIME_WAIT狀態;
3、設定 l_onoff 為非0,l_linger為非0,當套介面關閉時核心將拖延一段時間(由l_linger決定)。如果套介面緩衝區中仍殘留資料,進程將處於睡眠狀態,直 到(a)所有資料發送完且被對方確認,之後進行正常的終止序列(描述字訪問計數為0)或(b)延遲時間到。此種情況下,應用程式檢查close的傳回值是非常重要的,如果在資料發送完並被確認前時間到,close將返回EWOULDBLOCK錯誤且套介面發送緩衝區中的任何資料都丟失。close的成功返回僅告訴我們發送的資料(和FIN)已由對方TCP確認,它並不能告訴我們對方應用進程是否已讀了資料。如果套介面設為非阻塞的,它將不等待close完成。
struct linger so_linger;
...
so_linger.l_onoff = TRUE;
so_linger.l_linger = 0;
z = setsockopt(s,
SOL_SOCKET,
SO_LINGER,
&so_linger,
sizeof so_linger);
rox認為最好tcp伺服器設定方案:必須依靠用戶端發送close,server不主動發送close!!!server只處理逾時close和正常接收0位元組的cloes。