前几天一个技术群里的小伙伴@我 问netty中.childOption(ChannelOption.SO_RCVBUF, XX)
设置了没有效果, 抓包显示TCP的滑动窗口依然我行我素:)
我把我当时的回答再稍加修饰润色一下:
第一个误区就是: TCP在三次握手建立连接期间就会通过ACK分组通告自己的初始接收窗口(通告
窗口)大小, 而上边的代码是netty在连接建立成功后才设置的, 所以必然是无效的设置, 正确
的方法是设置到ServerSocket上, 也就是Option(Option.SO_RCVBUF, XX), 一个连接被
ServerSocket accept后会clone一个此连接对应的socket, 这个值会继承过来.
还有一个误区就是: 其实并不是rcv_buf设置多大, 通告窗口就多大的, 他们之间有非比寻常的
关系, 但绝对不是一一对应的关系, TCP是一种慢启动的协议, linux2.6.39版本之前, 在以
太网环境中初始通告窗口是的3个MSS(MSS即最大的segment size, 以太网环境中是1460个字
节)然后根据拥塞避免算法一点一点增加, 3.x内核初始通告窗口是直接在代码中写死的10个MSS
(是google一篇论文的建议).
第三点是我担心有人会这么想, 强调下recv_buf并不是个数组啥的(内核buf的数据结构大致是
一个segment queue), 也不会预先分配内存, 只是个接收缓冲区size的最大限制, 对端不给
你发数据, 内核不会自作多情分配内存给你, 要不然现在动辄单机上百万个长连接就是痴人说梦
了
总结: 通常情况下, 我个人经验是不建议设置rcv_buf, linux内核会对每一个连接做动态的
调整, 一般情况下足够智能, 如果设置死了, 就失去了这个特性, 尤其是大量长连接的应用,
我觉得这个设置就忘记吧, 要调优, 也最好到linux内核里面去配置对应参数.
2.6.32内核代码(/net/ipv4/tcp_input.c):
2.6.39内核代码(/net/ipv4/tcp_input.c, /include/net/tcp.h):