zoukankan      html  css  js  c++  java
  • 【Linux】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这个函数的这段代码:
     
     1       case SO_SNDBUF:
     2                         /* Don't error on this BSD doesn't and if you think
     3                            about it this is right. Otherwise apps have to
     4                            play 'guess the biggest size' games. RCVBUF/SNDBUF
     5                            are treated in BSD as hints */
     6  
     7                         if (val > sysctl_wmem_max)//val是我们想设置的缓冲区大小的值
     8                                 val = sysctl_wmem_max;//大于最大值,则val值设置成最大值
     9  
    10                         sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
    11                         if ((val * 2) < SOCK_MIN_SNDBUF)//val的两倍小于最小值,则设置成最小值
    12                                 sk->sk_sndbuf = SOCK_MIN_SNDBUF;
    13                         else
    14                                 sk->sk_sndbuf = val * 2;//val的两倍大于最小值,则设置成val值的两倍
    15  
    16                         /*
    17                          *      Wake up sending tasks if we
    18                          *      upped the value.
    19                          */
    20                         sk->sk_write_space(sk);
    21                         break;
    22  
    23                 case SO_RCVBUF:
    24                         /* Don't error on this BSD doesn't and if you think
    25                            about it this is right. Otherwise apps have to
    26                            play 'guess the biggest size' games. RCVBUF/SNDBUF
    27                            are treated in BSD as hints */
    28  
    29                         if (val > sysctl_rmem_max)
    30                                 val = sysctl_rmem_max;
    31  
    32                         sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
    33                         /* FIXME: is this lower bound the right one? */
    34                         if ((val * 2) < SOCK_MIN_RCVBUF)
    35                                 sk->sk_rcvbuf = SOCK_MIN_RCVBUF;
    36                         else
    37                                 sk->sk_rcvbuf = val * 2;
    38                         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 手册:
    1             SO_RCVBUF:              
    2                     Sets or gets the maximum socket receive buffer in bytes.  
    3                     The kernel doubles this value (to allow space for bookkeeping overhead) when it                     is set using setsockopt(2), 
    4                     and this doubled value is returned by getsockopt(2).
    5                     The default value is set by the /proc/sys/net/core/rmem_default file, 
    6                     and the maximum allowed value is set by the /proc/sys/net/core/rmem_max file.  
    7                     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中)。
     
    另一文章中简单介绍:http://www.linuxidc.com/Linux/2012-08/68874.htm
    1. tcp 收发缓冲区默认值
    [root@ www.linuxidc.com]# cat /proc/sys/net/ipv4/tcp_rmem  
    4096    87380   4161536
    87380  :tcp接收缓冲区的默认值
    [root@ www.linuxidc.com]# cat /proc/sys/net/ipv4/tcp_wmem 
    4096    16384   4161536
    16384  : tcp 发送缓冲区的默认值

    2. tcp 或udp收发缓冲区最大值
    [root@ www.linuxidc.com]# cat /proc/sys/net/core/rmem_max 
    131071
    131071:tcp 或 udp 接收缓冲区最大可设置值的一半。
    也就是说调用 setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen);  时rcv_size 如果超过 131071,那么
    getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 去到的值就等于 131071 * 2 = 262142
    [root@ www.linuxidc.com]# cat /proc/sys/net/core/wmem_max  
    131071
    131071:tcp 或 udp 发送缓冲区最大可设置值得一半。
    跟上面同一个道理

    3. udp收发缓冲区默认值
    [root@ www.linuxidc.com]# cat /proc/sys/net/core/rmem_default   
    111616:udp接收缓冲区的默认值

    [root@ www.linuxidc.com]# cat /proc/sys/net/core/wmem_default 
    111616
    111616:udp发送缓冲区的默认值

    4. tcp 或udp收发缓冲区最小值
    tcp 或udp接收缓冲区的最小值为 256 bytes,由内核的宏决定;
    tcp 或udp发送缓冲区的最小值为 2048 bytes,由内核的宏决定
  • 相关阅读:
    Linux基础网络设置
    CentOS安装
    一.Linux常用命令
    C# 的 ListView 中 多个 Items 的 批量移动方法
    用 Directory.GetFiles 过滤多种类型的文件
    Visual Studio 返回上次编辑位置的快捷键
    C# 的 DataGripView 在大数据时,如何加速?
    webapi和mvc 路由详解
    C# 实体类和DataTable相互转换
    WinForm的DataGridView 下拉滚动条消失
  • 原文地址:https://www.cnblogs.com/shihuvini/p/9927549.html
Copyright © 2011-2022 走看看