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


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中)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM