TCP之网络优化
上一篇文章我提到了Nagle算法,是为了解决报头大数据小从而导致网络利用率低的问题,这其实会带来新的问题。除此之外我们一起来看看tcp还会有什么优化策略呢!本文纯属学习记录,不完善或错误之处若指正将不胜感激。如有被误导的朋友,望海涵。
首先我们先康康Nagle算法
Nagle算法规则
- (1)如果包长度达到MSS,则允许发送;
- (2)如果该包含有FIN,则允许发送;
- (3)设置了TCP_NODELAY选项,则允许发送;
- (4)未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送;
- (5)上述条件都未满足,但发生了超时(一般为200ms),则立即发送。
延迟ACK
ACK机制中,在接收方收到一个包之后会先检查是否需要立即回应ACK,否则进入延迟ACK逻辑。 参考,
优点显而易见,提高了网络信道的利用率
当Nagle遇见延迟ACK
假想一个场景 MSS为8个中文字(最大报文长度)
甲需要发送两个应用层报文给乙——“你好”!“我是甲”。显然这两个报文都是不足8的,但是由于“你好”满足Nagel的第4条规则所以会第一时间发送出去,由于ACK延迟,甲迟迟收不到乙的确认。于是等到超时发送。
这会产生一个明显的延迟
解决
- 关闭Nagle算法,使用TCP套接字选项TCP_NODELAY可以关闭套接字选项(不推荐,有更多的优化策略)
- 使用writev,而不是两次调用write,单个writev调用会使tcp输出一次而不是两次,只产生一个tcp分节,这是首选方法
流量控制之滑动窗口
滑动窗口是为了平衡发送方和接收方速率不匹配,发送窗口在连接建立时由双方商定。但在通信的过程中,一般由接收方反馈本身的缓冲区大小从而动态调节发送窗口(缓冲区)大小
拥塞控制
为了方便,我们假设主机A给主机B传输数据
我们知道,两台主机在传输数据包的时候,如果发送方迟迟没有收到接收方反馈的ACK,那么发送方就会认为它发送的数据包丢失了,进而会重新传输这个丢失的数据包。
然而实际情况有可能此时有太多主机正在使用信道资源,导致网络拥塞了,而A发送的数据包被堵在了半路,迟迟没有到达B。这个时候A误认为是发生了丢包情况,会重新传输这个数据包。
结果就是不仅浪费了信道资源,还会使网络更加拥塞。因此,我们需要进行拥塞控制
慢开始和拥塞避免
- 在建立连接之后是如何确定拥塞窗口的大小?(拥塞窗口和滑动窗口注意区别)
- 第一种策略,第一次发送一个包,如果没有丢失就+1,以此类推
- 第二种策略,第一次发送一个包,如果没有丢失就乘以2,以此类推
所以二者取其长,在前期使用指数增长,当到达某一个数值之后进行线性增长
但是无论是指数增长还是线性增长最终都会到达一个MAX值,此时会重新以1开始启动并把阈值设置为MAX/2
我们把确定拥塞窗口大小的过程中指数增长阶段称之为 慢开始,线性增长阶段称之为 拥塞避免
快速重传与快速恢复
前面说过了,当出现网络拥塞时会重启慢开始过程
- 怎么判断网络拥塞?
- 当网络拥塞时,会出现大量的丢包
- 超时重发(丢包)一定是网络拥塞吗?
- 网络拥塞会导致大量的包触发超时重发事件。而当一个单独的包出现损坏或者丢包时,也会导致超时重发,所以超时重发不一定是网络拥塞
- 如何判断超时重发的原因
- 网络拥塞会导致大量的丢包
- 单个的丢包,由于延迟ACK规则,后序到达的每到达一个包,接收端都会回复相同的ACK。故当发送方接收到三个相同的ACK时,表明发生了单个的丢包
单个丢包事件,当发送方接收到三个相同的ACK时,此时发送方不必等待序号为ACK-1包的超时,会立即重发。并把当前的阈值设置为MAX,新的阈值为MAX/2,以 拥塞窗口 = MAX/2 进行增长
重发阶段我们称之为 快速重传 ,窗口参数的调整阶段称之为 快速恢复