数据流与窗口机制( 流量控制 )
由于TCP 连接双方每一次等待ACK 才能发起另一个请求的规则效率太慢,所以引入了窗口机制,该规则允许发送端批量发送数量等于窗口大小的数据。接收端进行缓存处理。在双方通信时,将窗口大小的值带入TCP 报文内。如果由于数据过多而导致程序繁忙无法处理请求数据,TCP 将会减小窗口大小,此时,另一端将会根据该值进行调整发送请求速率,来实现流量的控制。
例如老师在讲课。
老师读,小明在记录。 老师读:床前明月光,疑是地上霜。举头望明月,低头思故乡。 学生写:床前明月光,疑是…. ( 学生跟不上老师讲的 )此时,学生( 接收端 )已经跟不上。只能任由老师 ( 发送端 ) 发挥。这就是简单的流量发送机制,类似 UDP 这种无流量控制。
接下来他们换了一种方式:
老师读一个字,小明记一个字。 老师读:床 学生写:床 老师读:前 学生写:前 老师读:明 老师写:明 …… ( 下课了 ) 老师:算了,我要下班了。这种方式保证了学生( 接收端 )可以无误的接收,但是效率太低了。类似无窗口机制的TCP 连接。
接下来他们进行协商,得出了一个更好的策略。
老师读,学生来反馈 老师读:床前明月光。 学生写:床前明月光。 学生说:好,再来5个字。 老师读:疑是地上霜。 学生写:疑是… 学生说:没记住,重来。来2个字。 老师读:疑是。 学生写:疑是。 学生说:好,再来3个。 老师读:地上霜。 学生写:地上霜。 学生说:好,给我来10个。 老师读:举头望明月,低头思故乡。 学生写:举头望明月,低头思故乡。经过此方法,学生( 接收端 )和老师 ( 发送端 )达成了一致,即当学生 ( 接收端 ) 状态好的时候可以通知老师( 发送端 )多发一点,而状态差的时候则少发一点。
滑动窗口滑动窗口就是 TCP 窗口机制的实现。
如图所示: 初始状态下,我们提供的窗口大小为 6。接下来,我们将逐步讲解窗口滑动时的机制。
正常状态:1,2,3已经发送完毕,并且已经收到Ack 报文。 4,5,6表示已经发送了,但是并没有接收到对方的ACK 报文,所以无法确认对方是否收到。7,8,9表示我们接下来将要发送的包。后面的10,11,12.. 都还没被读入内存,所以要等4 接收ACK 报文后才会使窗口右移,使得有空间继续发送。
丢包状态:当4 一直无法获取对方的 ACK 报文 ( 丢包 ),在这期间我们仍会窗口内即将发送的包全部发送。但由于窗口机制的限制,我们会一直等待4 的ACK 报文后才会使得滑动窗口右移。
在长时间的等待下,我们会触发重传机制来重新发送ACK 报文来解决丢包状态下滑动窗口等待的问题。
注意:由于Ack 报文是要按顺序的。必须要等4的Ack收到,才会把5-9的Ack报文发送过去。这样就保证了滑动窗口的顺序。
TCP 拥塞算法
相比于端到端的流量控制,那么全局性的网络拥塞该如何解决呢?
TCP 使用拥塞算法让每一个发送方根据所感知到的网络拥塞控制来限制其能向连接发送流量的速率。发送端会维护一个拥塞窗口,来对一个TCP 发送方能向网络中发送流量的速率进行限制。
TCP 拥塞算法主要包括三个部分:
慢启动在TCP 双方连接建立后,发送方将会为维护一个拥塞窗口的值( cwnd ),初始为 1个MSS( 最大报文长度 ),和另一个值 ssthresh ( 慢启动阈值 )= cwnd/2。
主要过程为:当开始发送时根据cwnd 将发送 1 个报文段。每接收到一次确认后就增加1 个MSS。也就是下一次将会发送 2 个报文段.. 4 个报文段 ..8个报文段。( 指数增长 )
那么,何时结束慢启动状态呢?
如果存在一个由超时指示的丢包事件,TCP发送方将 cwnd 设置为1并重新开始慢启动。 如果检测到cwnd到达或超过ssthresh时,结束慢启动并转移到拥塞避免模式。 如果检测到3个冗余ACK,就执行快速重传并进入快速恢复状态。 拥塞避免我们是在cwnd 超过ssthresh 的时候转为拥塞避免的状态,因为如果在cwnd已经达到或者超过ssthresh 时还继续以慢启动的指数增长方式,有可能会带来拥塞。所以在超过阈值时我们将会使其值进行线性增长。
假设一次发送10个包,那我们将每次在接收到ACK 报文时增加 10/1 个MSS 来限制其速度呈线性增长。
快速恢复当数据在网络中发生丢失时,由于还有部分数据还在互联网中向接收方流动,TCP协议并不想突然执行慢启动( cwnd设置为1)来减少数据流的发送。
主要过程为:
当收到3个重复ACK时,把ssthresh设置为cwnd的一半,把cwnd设置为ssthresh的值加3,然后重传丢失的报文段,加3的原因是因为收到3个重复的ACK,表明有3个“老”的数据包离开了网络。 再收到重复的ACK时,拥塞窗口增加1。 当收到新的数据包的ACK时,把cwnd设置为第一步中的ssthresh的值。原因是因为该ACK确认了新的数据,说明从重复ACK时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态。TCP 和 UDP 的区别是什么 ?
TCP 粘包问题 ( 题外话 )
当你去面试或者在社群讨论时经常会听到一个错误的言论,那就是如何解决 TCP 粘包问题。
问题背景
在进行 TCP 进行传输数据时,可能由于发送的速度过快,导致我们接收数据时会被分割。例如:
我是1 我是2 我是3我 是4 我是5在上面的示例中 “我是3我” 发生了粘包。
错在哪儿
那么,怎么说 TCP 粘包是一个错误的言论呢?
由于 TCP 是一个底层通信传输协议,它所提供的规则是基于字节流而不是消息包。它所做的事情是把数据变成字节流发到接收端去,而且保证顺序不会乱。但是如何解析需要你自己来做。
如何解决
需要在上层通信传输协议中进行明确规定区分。例如对每条信息进行设置一个带包头的应用层报文结构,包头定长,以特定标志开头,里面有负载长度。接收端就可以根据该规则进行解析。
免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:物联网传输协议基石 – TCP ( Transmission Control Protocol )下 https://www.yhzz.com.cn/a/12706.html