TCP

TCP可靠性传输

TCP可靠性传输

Posted by Lerko on September 9, 2020

TCP的特点及其目的

就一个

可靠性,需要解决数据破坏,丢包,重复,分片顺序混乱的问题

如何实现可靠传输

算法

  1. 慢启动
  2. 拥塞避免
  3. 快速重传
  4. 快速恢复

窗口

  1. 滑动窗口:传输效率,快速重传
  2. 拥塞窗口:流量控制,快速恢复

序列号和确认应答

TCP通过ACK(确认应答),来实现可靠的传输。 就是对方收到之后需要进行一个回复,这个回复中包含数据的序列号。 序列号和应答机制是TCP可靠传输的基础

超时重发

在网络中发生的包有可能RTT(时间波动值方差,表示离散值)很大。 因为同一个时间段中的包可能是通过不同的网络线路过来的。

超时重发需要有一个双方定义的时间间隔,Unix,Window中都是以0.5秒未控制单位,重发时间 都是0.5秒的整数倍

连接管理

可靠的传输必须有可靠的连接

所以tcp有三次的握手连接,和4次挥手。所以连接管理需要7个包才能完成

为什么需要三次握手可以另外一篇文章,总结是:防止历史连接请求导致的错误

20200907113952

发送数据的单位

tpc可靠传输中是以段未单位发送,在建立连接的时候会通过SYN包确认MSS(最大消息长度)。 理想情况是最大的长度正好是ip中不会被分片处理的大小

滑动窗口

20200909102655

传输效率:窗口扩大了确认区间,可以从单次应答等待,提升为批量应答等待。使用了缓冲区,用来进行多段同时应答的功能。

滑动窗口重发控制:快重传

考虑应答没有返回的情况

在没有使用窗口控制的时候,没有收到确认应答的数据都会被重发。当我们使用了滑动窗口,某些确认应答丢失我们页无需重发,可以通过下一次应答来确认。

20200909095833

如果窗口前端的数据没有接收到,未接收到的一方就会进行3次ACK. 当收到前端缺失的数据,窗口就向前滑动了

20200909100356

滑动窗口流控制

如果在传输中,由于发送的数据包太多,接收端可能收到一些对于接收端没有意义的数据包, 这样的话就会导致很多包被丢弃,出发重传机制

为了防止这个现象出现,滑动窗口限制了数据的发送范围,让两端都有接收的范围。 TCP中有一个特殊的字段可以用来通知设置窗口大小。网络吞吐量越大,窗口值越高。

窗口大小是会变化的,这样就可以动态控制窗口大小可以和网络吞吐量适配。 主机端会时不时发生窗口更新通知到客户机。

拥塞控制:慢启动

因为网络负载能力有限,可能有多个主机使用同一个网络设备。 如果每个设备都发送大量的包,那么网络必定会瘫痪。 具体一点,我们知道TCP通过一个timer采样了RTT并计算RTO,但是,如果网络上的延时突然增加,那么,TCP对这个事做出的应对只有重传数据,但是,重传会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,于是,这个情况就会进入恶性循环被不断地放大。试想一下,如果一个网络内有成千上万的TCP连接都这么行事,那么马上就会形成“网络风暴”,TCP这个协议就会拖垮整个网络。这是一个灾难。

为了处理这个问题,TCP通过一个叫慢启动的算法来对发送的数据量进行控制 刚刚加入网络的连接,一点一点地提速,不要一上来就像那些特权车一样霸道地把路占满

为了调节发送段的数据量,TCP定义了一个拥塞窗口 窗口限定了一个区间,让TCP只发送窗口区域中的数据,以免发送的数据过多或者过少

雍塞窗口的初始值都是1,每个应答ACK收到之后都会+1。发送数据包的时候将窗口大小和接收端的做比较, 按照他们中小的值发生比这个值还要小的数据量。

这样我们就实现了慢启动,但是这个应答每次都会+1,甚至段时间没指数增加。 为了防止这个问题,我们引入了慢启动阀值,只要窗口大小超过了这个值,就只允许按照下面的比例放大窗口:

一个数据段字节数/拥塞窗口(字节)*一个数据段字节数

快恢复

快恢复是将拥塞控制快速恢复到平衡状态的一种算法

比如一旦出现超时重传,tcp就会把慢启动阀值 ssthresh 的值设置为 cwnd(拥塞窗口) 值的一半,同时 cwnd 设置成 1. 但是快恢复算法不这样做。

一旦出现超时重传,或者收到第三个重复的 ack 时(快重传),TCP 会把慢启动门限 ssthresh 的值设置为 cwnd 值的一半,同时 cwnd = ssthresh (在有些版本中,会让 cwnd = ssthresh + 3)。

20200909104626

实际上,现代的 Linux 内核版本早已都不采用上面这些 TCP 版本了,而是使用使用的 TCP Cubic 版本。那为什么还要学呢?这就好比你想学会走,你就得先学会爬,简单的先弄会,以后再自学复杂的。