TCP选项之SO_RCVBUF和SO_SNDBUF
每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式以及TCP的滑动窗口便是依赖于这两个独立的buffer以及此buffer的填充状态。接收缓冲区把数据缓存入内核,应用进程一直没有调用read进行读取的话,此数据会一直缓存在相应socket的接收缓冲区内。再啰嗦一点,不管进程是否读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲区之中。read所做的工作,就是把内核缓冲区中的数据拷贝到应用层用户的buffer里面,仅此而已。进程调用send发送的数据的时候,最简单情况(也是一般情况),将数据拷贝进入socket的内核发送缓冲区之中,然后send便会在上层返回。换句话说,send返回之时,数据不一定会发送到对端去(和write写文件有点类似),send仅仅是把应用层buffer的数据拷贝进socket的内核发送buffer中。
每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。
接收缓冲区被TCP和UDP用来缓存网络上来的数据,一直保存到应用进程读走为止。对于TCP,如果应用进程一直没有读取,buffer满了之后,发生的动作是:通知对端TCP协议中的窗口关闭。这个便是滑动窗口的实现。保证TCP套接口接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP的流量控制,如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。 UDP:当套接口接收缓冲区满时,新来的数据报无法进入接收缓冲区,此数据报就被丢弃。UDP是没有流量控制的;快的发送者可以很容易地就淹没慢的接收者,导致接收方的UDP丢弃数据报。
以上便是TCP可靠,UDP不可靠的实现。
这两个选项就是来设置TCP连接的两个buffer尺寸的。
来自:http://blog.chinaunix.net/uid-20726500-id-4949695.html
为了达到最大网络吞吐,socket send buffer size(SO_SNDBUF)不应该小于带宽和延迟的乘积。
之前我遇到2个性能问题,都和SO_SNDBUF设置得太小有关。
但是,写程序的时候可能并不知道把SO_SNDBUF设多大合适,而且SO_SNDBUF也不宜设得太大,浪费内存啊。
于是,有OS提供了动态调整缓冲大小的功能,这样应用程序就不用再对SO_SNDBUF调优了。
(接受缓冲SO_RCVBUF也是类似的问题,不应该小于带宽和延迟的乘积)。
On Linux:
Linux从2.4开始支持接收缓冲和发送缓冲的动态调整。
http://www.man7.org/linux/man-pages/man7/tcp.7.html
------------------------------------------------------------
tcp_rmem (since Linux 2.4)
This is a vector of 3 integers: [min, default, max]. These
parameters are used by TCP to regulate receive buffer sizes.
TCP dynamically adjusts the size of the receive buffer from
the defaults listed below, in the range of these values,
depending on memory available in the system.
...
tcp_wmem (since Linux 2.4)
This is a vector of 3 integers: [min, default, max]. These
parameters are used by TCP to regulate send buffer sizes. TCP
dynamically adjusts the size of the send buffer from the
default values listed below, in the range of these values,
depending on memory available.
------------------------------------------------------------
- [root@node2 ~]# cat /proc/sys/net/ipv4/tcp_rmem
- 4096 87380 4194304
- [root@node2 ~]# cat /proc/sys/net/ipv4/tcp_wmem
- 4096 16384 4194304
On Windows:
Windows上其实有类似的机能,但是Windows的文档太糟糕了,我废了不少劲才找到一些旁证。
从Vista开始Windows引入接受窗口的自动调整
http://blogs.msdn.com/b/wndp/archive/2007/07/05/receive-window-auto-tuning-on-vista.aspx
从Win7和Win2008R2开始Windows引入送信缓冲的自动调整
https://technet.microsoft.com/zh-cn/subscriptions/ms740642.aspx
------------------------------------------------------------
Updated for Windows 7 and Windows Server 2008 R2
...
Dynamic send buffering for TCP was added on Windows 7 and Windows Server 2008 R2. As a result, the use of the SIO_IDEAL_SEND_BACKLOG_CHANGE andSIO_IDEAL_SEND_BACKLOG_QUERY IOCTLs are needed only in special circumstances. For more information, see SIO_IDEAL_SEND_BACKLOG_QUERY.
------------------------------------------------------------
需要注意的是,如果应用设置了SO_SNDBUF,Dynamic send buffering会失效 。
https://msdn.microsoft.com/en-us/library/windows/desktop/bb736549(v=vs.85).aspx
------------------------------------------------------------
Dynamic send buffering for TCP was added on Windows 7 and Windows Server 2008 R2. By default, dynamic send buffering for TCP is enabled unless an application sets the SO_SNDBUF socket option on the stream socket.
------------------------------------------------------------
我在MSDN上没有找到正式介绍这个功能的页面(也许就没有这样的页面),所以也不知道它的自动调整是怎么个调法,范围是多少。而且,通过对Win7和Windows Server 2008 R2的测试我也没看到送信缓冲自动调整的效果,这个效果我只在Windows 2012上看到了。
测试:
下面是我的测试,主要针对送信缓冲的。
以下是各OS中送信缓冲的缺省值
OS 送信缓冲的缺省值(通过getsockopt(SO_SNDBUF)获取)
Window7: 8k
Windows2003: 8k
Windows2008: 8k
Windows8: 64k
Windows2012: 64k
测试方法:
1)机器A(Windows)通过TCP socket向机器B发送100MB数据。
2)机器A每次send()向socket写入8K字节。
3)机器A的程序设置不同的SO_SNDBUF,查看总送信时间的变化。
测试环境1:
Host A: Windows 2012(x64)
Host B: RHEL6(x64)
Network:1Gbit LAN
Result(execute time):
default(64K), 1.118s(送信缓冲的自动调整生效)
set SO_SNDBUF to 32K, 3.295s
set SO_SNDBUF to 64K, 2.048s
set SO_SNDBUF to 128K, 1.404s
set SO_SNDBUF to 256K, 1.290s
从上面可以看出, Windows 2012中送信缓冲的自动调整还是很有效果的。
注)如果使用Windows而不是Linux作为客户端,效果也是一样的
测试环境2:
Host A: Windows 2008 R2(x64)
Host B: RHEL6(x64)
Network:1Gbit LAN
Result(execute time):
default(8K), 7.370s
set SO_SNDBUF to 32K, 4.159s
set SO_SNDBUF to 64K, 2.875s
set SO_SNDBUF to 128K, 1.593s
set SO_SNDBUF to 256K, 1.324s
对Windows 2008 R2,不知道送信缓冲的自动调整没有生效("netsh winsock show autotuning"是生效了的),还是8K初始值的起点太低,反正性能不如人意。
结论:
较新的OS都支持socket buffer的自动调整,不需要应用程序去调优。但对Windows 2012(和Win8)以前的Windows,为了达到最大网络吞吐,还是要应用程序操心一下SO_SNDBUF的设置。
TCP选项之SO_RCVBUF和SO_SNDBUF的更多相关文章
- UNIX网络编程——套接字选项(SO_RCVBUF和SO_SNDBUF)
有时候我们需要控制套接字的行为(如修改缓冲区的大小),这个时候我们就要学习套接字选项. int getsockopt(int sockfd,int level,int optname,void *op ...
- tcp选项TCP_DEFER_ACCEPT
tcp选项TCP_DEFER_ACCEPT http://blog.chinaunix.net/uid-23207633-id-274317.html 之前在项目测试的时候,如果第三次握手发完裸ack ...
- TCP连接建立系列 — TCP选项解析
本文主要分析:在收到客户端的SYN包时,服务器端是如何解析它所携带的TCP选项,并结合本端情况决定是否予以支持. 内核版本:3.6 Author:zhangskd @ csdn blog 概述 收到客 ...
- 常用的TCP选项
MSS选项:通知最大可接收量.发送SYN的TCP一端使用本选项通告对端它的最大分节大小(maximum segment size)即MSS,也就是它在本连接的每个TCP分节中愿意接受的最大数据量.发送 ...
- TCP 选项RST
1.RST介绍 RST表示reset复位,用于异常情况下关闭连接. 发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓冲区中的包. 而接收端收到RST包后,也不必发送ACK包来确认. 2. ...
- TCP选项之SO_LINGER
SO_LINGER这个选项在我以前带队改造haproxy的时候引出过一个reset(RST)客户端连接的bug. SO_LINGER作用设置函数close()关闭TCP连接时的行为.缺省close() ...
- 【转】TCP之深入浅出send和recv
本篇我们用一个测试机上的阻塞socket实例来说明主题.文章中所有图都是在测试系统上现截取的. 需要理解的3个概念 1. TCP socket的buffer 每个TCP socket在内核中都有一个发 ...
- Linux-TCP之深入浅出send和recv
内容摘自:TCP之深入浅出send和recv.再次深入理解TCP网络编程中的send和recv 建议阅读时参考:Unix环境高级编程-TCP.UDP缓冲区 概念 先明确一个概念:每个TCP socke ...
- Linux-TCP之深入浅出send和recv【转】
转自:https://www.cnblogs.com/JohnABC/p/7238417.html 内容摘自:TCP之深入浅出send和recv.再次深入理解TCP网络编程中的send和recv 建议 ...
随机推荐
- Jenkins的安装及使用(一)
操作环境:Windows7 一.环境准备 1 安装JDK 本文采用jdk-8u111-windows-x64.exe: 安装完成后配置环境变量. 2 配置tomcat 本文采用tomcat8,免安装版 ...
- 分模块开发创建dao子模块——(七)
1.选中父工程右键新建maven module
- rtop:一个通过 SSH 监控远程主机的交互式工具【转】
编译自: http://www.tecmint.com/rtop-monitor-remote-linux-server-over-ssh/ rtop[1] 是一个基于 SSH 的直接的交互式远程系统 ...
- Jmeter遇到Connection reset by peer的解决方法
解决方案如下: 1.修改HTTP请求下面的Impementation选项,改成HttpClient4 2.修改了/bin/jmeter.bat文件:找到这2行 set HEAP=-Xms256m -X ...
- 【Unity_UWP】Unity 工程发布win10 UWP 时的本地文件读取 (下篇)
Universal Windows Platform(UWP)是微软Windows10专用的通用应用平台,其目的在于在统一操作系统下控制所有智能电子设备. 自从Unity 5.2之后,配合VS 201 ...
- windows 2008 启用.NET Framework 3.5
Win2008下已经集成了.NET 3.5.1 framework,需要在管理界面打开! 方法和步骤是: 服务器管理器 -> 功能 -> 添加功能 然后在“选择功能”界面勾选“.NET F ...
- Oracle-查询最近更新的前10条数据
在实际用途中,常常会要求取最近的几条纪录,这就需要先对纪录进行排序后再取rownum <= 一般常见的 SELECT * FROM (SELECT a.* FROM torderdetail a ...
- SQL Server 3
一.数据压缩 1.行压缩 行压缩可将固定长度类型存储为可变长度存储类型.例如,使用char(100)数据列存储字符串“SQL Server 2012”,压缩后只需要存放15个字符.(这种压缩模式,将对 ...
- ajax test
(function ($) { function loadNode(obj){ obj.closest('.filter').find('.item').removeClass('select'); ...
- 工作流调度器azkaban2.5.0的安装和使用
为什么需要工作流调度系统 一个完整的数据分析系统通常都是由大量任务单元组成: shell脚本程序,java程序,mapreduce程序.hive脚本等 各任务单元之间存在时间先后及前后依赖关系 为了很 ...