TCP 可靠传输,流量控制,拥塞控制是时候看一篇搞定一下了

404 阅读9分钟

目录

抓包过程以及TCP包首部

使用了 Wireshark 进行抓包,用两个最常用的 curl 和 ping 命令来演示抓包情况,开启抓包。

## 先访问我自己的网站首页
 curl https://zengzhiqin.kuaizhan.com 
## 再查看我自己网站的地址
 ping https://zengzhiqin.kuaizhan.com

Wireshark根据 ping 命令得到的地址进行条件过滤,得到上面两个命令所得到的包,主要有 TCP(https基于tcp协议)协议和 ICMP(ping命令是基于 ICMP 协议)协议的包,如下图所示:

抓包分析
抓包分析
TCP首部数据一一对应
TCP首部数据一一对应
TCP头部
TCP头部

可靠传输

TCP 实现可靠传输的四种实现方法:

  1. 校验
  2. 序号
  3. 确认
  4. 重传

第1,2两种机制,在我公众号另外一篇有详细讲解,这里我主要讲述第3,4种。

可靠传输目的: 就是要让发送方发送的所有数据,接收方都能完整,按序收到。

正如宫本武藏的口头禅“排好队,一个一个来”一样,使用最笨的方法来解决最难的问题,既然你要可靠那么就一个一个确认,只要你没告诉我你收到了,那么我就一直重发

可靠传输的工作原理:停止等待协议

可靠与不可靠解决方式
可靠与不可靠解决方式

我分为了四张图,竖线代表的是时间轴,RTT代表数据包发过去然后确认包发回来的往返时间,分别是”无差错你好我好大家好的情况下“,”发送超时或者失败“情况下,”确认超时“和”确认丢失“的情况下来分析的。通过这种确认重传机制,TCP就可以实现可靠传输,也就是第3,4点的实现方式。需要知道的一点是,重传这个动作是发送方自发行为,并不需要接收方通知它进行重传。

窗口概念引出

上面的方法,确实不错哈,用了最简单的方法解决了可靠传输这个问题,可是网络时时刻刻那么忙,我等你一来一回的确认宫本武藏一个大招跳出去估计是一节一节的落地了,黄花菜都凉了。

上述停止等待协议最大的问题是信道利用率太低了

停止等待传输
停止等待传输

RTT时间是由网络状况决定拯救不了,T2一般也是固定的,由公式可看出,想要提高信道利用率只能从 T1 下手。

流水线传输
流水线传输

发送方可以连续发送多个包,不用每次都停下来等待确认再继续发,将上面这些的连续发送的包用一个窗口来包含起来即TCP窗口的由来,如下图:

滑动窗口
滑动窗口

既然你发送方为了不一个一个包发可以有窗口技术,那么我接收方肯定也不甘落后得学起来啊,即不进行一个一个确认,转而累积确认

接收方累积确认方式
接收方累积确认方式

接收窗口 rwnd 和发送窗口 cwnd

此处涉及到二个窗口:

  1. 接收窗口receiver window(即rwnd),是接收方根据自己的承受能力设置的接收缓存值大小,反映了接收方的接收能力,来做流量控制
  2. 拥塞窗口congestion window(即cwnd),是发送方根据网络拥塞程度设置的网络窗口值,发送窗口=min(rwnd,cwnd)即是接收窗口和拥塞窗口的最小值,来做拥塞控制

窗口数据结构如下:

窗口数据结构
窗口数据结构

其实看似这么高深的东西,一步步想过来竟是如此简单,感叹一句”啊,聪明的人类“(调皮一下哈哈哈)。

流量控制

上面说到了通过窗口可以增大信道的利用率,然后就是窗口的大小怎么设置,设置多大,窗口还可以用来做什么?

发送方如果发的过快,那么接收方就会来不及接受,就会丢包,这肯定不行啊,万一别人给我发了很多红包丢一个我都不想哒~

分段传输
分段传输

流量控制目的:让发送方根据网络状况动态的调整发送频率,好让接收方来得及接收。

TCP利用滑动窗口机制实现流量控制。发送方的发送窗口是动态变化的,取决于接收方返回的报文段的窗口大小,可能是数据报文段也可能是确认报文,因为TCP包首部都有窗口信息,还是这张图再看一下窗口数据: TCP首部数据一一对应

举例来说明具体TCP流量控制过程

A主机向B主机发送数据,建立连接的时候 B 告诉 A:”大哥,我的rwnd=400byte“,假设每个报文段都是100byte,初始序号是1,三次流量控制沟通过程如下: 流量控制例子

这张图,最后 rwnd=0 了,这种情况持续到接收端腾出了新的接收缓存之后 B会主动给 A发送他的新的 rwnd,0窗口通知的时候 A 就会一直等待接收方新的 rwnd 通知,为了防止新的 rwnd 丢失了,之前的文章很多都分析过这种情况,为了解决包超时收不到确认设置了等待一段时间就重传,四次挥手过程设置了最后需要等待 2MSL 时间发送端才关闭,这些时间都是通过设置计时器来计时,都是为了解决包丢失了造成死锁。同样这里为了解决新的 rwnd 丢失了造成 A 死锁发送端只要收到了0窗口通知就会启动计时器,若时间到了就会重新发送一个0窗口探测报文,接收方再回复现在的接收窗口。

疯狂试探
疯狂试探

拥塞控制

我家小区网络最好的时候是晚上3-6点,上午10-12点,下午3-5点,这些时间段我玩王者最畅快,晚上8-11点网络高峰时段每次卡一下回过神我就站在了泉水(真的好开心)。

试想一下原本网络就不好,然后你还一次性向网络倒那么多数据包,大家都别过去了都超时,然后超时时间到了又都重发,恶性循环下去使得原本就不富裕的网络更加雪上加霜,因此 TCP 你要自己学聪明,进行拥塞控制。 拥塞控制的目的就是防止过多的数据注入到网络中,网络堵塞使得包一直到不了接收端。

拥塞控制起到的作用
拥塞控制起到的作用

拥塞控制算法有四种:

  1. 慢开始
  2. 拥塞避免
  3. 快重传
  4. 快恢复

慢开始和拥塞避免算法

慢开始和拥塞避免算法
慢开始和拥塞避免算法

一个传输轮次指的是发送了一批报文段并且收到了确认的时间 RTT。

慢开始是指数增长,一直试探网络状况如果健康就一直指数增长。到了ssthresh值的时候,这是慢开始轮限值,开始线性增长,一直增长到网络拥塞的话,跳崖式降低一夜回到解放前,从1开始,将新的ssthresh值调低为原来拥塞时候的一半又开始指数增长,就这样动态的变化。

快重传和快恢复算法

快重传和快恢复算法
快重传和快恢复算法

从图可以看到这个算法前面和慢开始拥塞避免算法是一致的,主要是调整了跳崖式降低发送速率这个地方,这样从0开始效率太低了,如果是男女朋友间在发送微信岂不是被折磨的心痒痒。

拥塞窗口cwnd每次指数增长一次都是在收到了确认报文的情况下增长的,比如A发送1,23,4,5,6这些报文段,2丢失了,1345都收到了那么每次345收到都会给A发送确认1收到了的确认报文让他发2(这个地方上一篇有提到),这种算法就是在2的超时计时器到期之前收到了三个确认之后就马上重传2,接收方都催着要了哥,后面三个确认包都到了说明网络厚爱好的嘛就是你迷路了,因此进行快速重传还是将新的ssthresh值调低为原来拥塞时候的一半又开始指数增长,现在一般是用这种,上面那种方法犹豫效率太低了被淘汰了。

流量控制和拥塞控制的区别

流量控制是点到点的问题,一对一,如果接收方的数据来不及接收那么就能直接找到发送方这个罪魁祸首,主要是因为接收方来不及接受发送方的数据

拥塞控制是多对一,一个接收方 面对多个发送方出现了网络拥堵,接收方找不到具体的发送方,主要是因为网络发生了堵塞发送方数据迟迟到不了接收方

简单理解,拥塞控制是路上堵车,流量控制是停车场停车车位不够。

这篇内容陆陆续续写了好几天了,感觉概念性的东西很多,我已经尽量再用聊天式的轻松语气来写了。北京今天下雨了,五道口两旁的树木长得郁郁葱葱,抬头看见树叶将天空撕成了碎片,耳机里一直在循环毛不易低沉性感声线唱着的”一路山程“,我就这样撑着伞走在这个都市的心脏上,一路憧憬着未来。

感谢朋友们的观看,有收获的朋友点个在看鼓励一下吧,谢谢~

下期预告: 应用层的那些玩意儿,也是离我们最近的一层。