1. 程式人生 > >socket tcp緩沖區大小的默認值、最大值

socket tcp緩沖區大小的默認值、最大值

usr send p s ipv core treat 字節 net ron

Author:阿冬哥

Created:2013-4-17

Blog:http://blog.csdn.net/c359719435/

Copyright 2013 阿冬哥 http://blog.csdn.net/c359719435/

使用以及轉載請註明出處

1 設置socket tcp緩沖區大小的疑惑 疑惑1:通過setsockopt設置SO_SNDBUF、SO_RCVBUF這連個默認緩沖區的值,再用getsockopt獲取設置的值,發現返回值是設置值的兩倍。為什麽? 通過網上查找,看到linux的內核代碼/usr/src/linux-2.6.13.2/net/core/sock.c,找到sock_setsockopt這個函數的這段代碼:
case SO_SNDBUF:
/* Don‘t error on this BSD doesn‘t and if you think
about it this is right. Otherwise apps have to
play ‘guess the biggest size‘ games. RCVBUF/SNDBUF
are treated in BSD as hints */
if (val > sysctl_wmem_max)//val是我們想設置的緩沖區大小的值
val = sysctl_wmem_max;//大於最大值,則val值設置成最大值
sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
if ((val * 2) < SOCK_MIN_SNDBUF)//val的兩倍小於最小值,則設置成最小值
sk->sk_sndbuf = SOCK_MIN_SNDBUF;
else
sk->sk_sndbuf = val * 2;//val的兩倍大於最小值,則設置成val值的兩倍
/*
* Wake up sending tasks if we
* upped the value.
*/
sk->sk_write_space(sk);
break;
case SO_RCVBUF:
/* Don‘t error on this BSD doesn‘t and if you think
about it this is right. Otherwise apps have to
play ‘guess the biggest size‘ games. RCVBUF/SNDBUF
are treated in BSD as hints */
if (val > sysctl_rmem_max)
val = sysctl_rmem_max;
sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
/* FIXME: is this lower bound the right one? */
if ((val * 2) < SOCK_MIN_RCVBUF)
sk->sk_rcvbuf = SOCK_MIN_RCVBUF;
else
sk->sk_rcvbuf = val * 2;
break;
從上述代碼可以看出:(1)當設置的值val > 最大值sysctl_wmem_max,則設置為最大值的2倍:2*sysctl_wmem_max; (2)當設置的值的兩倍val*2 > 最小值,則設置成最小值:SOCK_MIN_SNDBUF; (3)當設置的值val < 最大值sysctl_wmem_max,且 val*2 > SOCK_MIN_SNDBUF, 則設置成2*val。 查看linux 手冊:
SO_RCVBUF:
Sets or gets the maximum socket receive buffer in bytes.
The kernel doubles this value (to allow space for bookkeeping overhead) when it is set using setsockopt(2),
and this doubled value is returned by getsockopt(2). The default value is set by the /proc/sys/net/core/rmem_default file,
and the maximum allowed value is set by the /proc/sys/net/core/rmem_max file.
The minimum (doubled) value for this option is 256.
查看我的主機Linux 2.6.6 :/proc/sys/net/core/rmem_max: 4194304 //4M 查看/proc/sys/net/core/wmem_max: 8388608 //8M 所以,能設置的接收緩沖區的最大值是8M,發送緩沖區的最大值是16M。 疑惑2:為什麽要有2倍這樣的一個內核設置呢?我的理解是,用戶在設置這個值的時候,可能只考慮到數據的大小,沒有考慮數據封包的字節開銷。所以將這個值設置成兩倍。 註:overhead,在計算機網絡的幀結構中,除了有用數據以外,還有很多控制信息,這些控制信息用來保證通信的完成。這些控制信息被稱作系統開銷。 2 tcp緩沖區大小的默認值 建立一個socket,通過getsockopt獲取緩沖區的值如下: 發送緩沖區大小:SNDBufSize = 16384 接收緩沖區大小:RCVBufSize = 87380 疑惑3:linux手冊中,接收緩沖區的默認值保存在/proc/sys/net/core/rmem_default,發送緩沖區保存在/proc/sys/net/core/wmem_default。
[root@cfs_netstorage core]# cat /proc/sys/net/core/rmem_default 1048576 [root@cfs_netstorage core]# cat /proc/sys/net/core/wmem_default 512488
可知,接收緩沖區的默認值是:1048576,1M。發送緩沖區的默認值是:512488,512K。為什麽建立一個socket時得到的默認值是87380、16384??? 進一步查閱資料發現, linux下socket緩沖區大小的默認值在/proc虛擬文件系統中有配置。分別在一下兩個文件中:
/proc/sys/net/ipv4/tcp_wmem [root@cfs_netstorage core]# cat /proc/sys/net/ipv4/tcp_wmem 4096 16384 131072 //第一個表示最小值,第二個表示默認值,第三個表示最大值。 /proc/sys/net/ipv4/tcp_rmem [root@cfs_netstorage core]# cat /proc/sys/net/ipv4/tcp_rmem 4096 87380 174760
由此可見,新建socket,選取的默認值都是從這兩個文件中讀取的。可以通過更改這兩個文件中的值進行調優,但是最可靠的方法還是在程序中調用setsockopt進行設置。通過setsockopt的設置,能設置的接收緩沖區的最大值是8M,發送緩沖區的最大值是16M(Linux 2.6.6中)。

socket tcp緩沖區大小的默認值、最大值