socket tcp緩衝區大小的預設值 最大值

2021-10-03 20:39:39 字數 4576 閱讀 4321

有乙個問題: 我搜尋了一些關於recvbuf/sndbuf的blog,基本上說的是recvbuf就是socket的滑動視窗大小,而滑動視窗大小是16位的,最大也就是64k, 你這邊讀取出來的資料已經超過64k了,是否我理解上有什麼偏差?

答:在tcp頭部只有16位來表示,所以它的最大值是65536,但是對於一些情況來說需要使用更大的滑動視窗,這時候就要使用擴充套件的滑動視窗,這時會使用擴充套件的32位的滑動視窗大小。

author:阿冬哥

created:2013-4-17 

blog:

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
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
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

[root@cfs_netstorage core]# cat /proc/sys/net/core/wmem_default

可知,接收緩衝區的預設值是: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緩衝區大小

socket緩衝區大小預設為64 k 理論上最優大小為 頻寬乘以往返時間 rtt通過ping ip位址的最後一行得到,如下圖所示 一般把緩衝區大小的最優化設定需要參照頻寬與往返時間rtt得到的頻寬延遲bdp。假設應用程式是通過乙個 100mbps 的區域網進行通訊,其 rtt 為 10 ms,那麼 ...

unix socket 的緩衝區大小

1 預設大小 tcp cat proc sys net ipv4 tcp rmem 4096 87380 4161536 其中 87380為預設接收緩衝的大小 cat proc sys net ipv4 tcp wmem 4096 16384 4161536 其中16384為預設傳送緩衝的大小 ud...

緩衝區設定 套接字緩衝區大小及限制

pv4資料報的最大值是65535位元組,包括ipv4首部。ipv6資料報的最大值是65575位元組,包括40位元組的首部。mtu ip資料報的最大傳輸單元,乙太網的mtu是1500位元組。ipv4要求的最小鏈路mtu是68位元組。ipv6要求的最小鏈路mtu是1280位元組。如果乙個ipv6的資料報...