驻马店做网站优化,网站推广关键词排名,微网站开发素材,开发中英文切换网站如何做序言 在上一篇文章中我们介绍了 TCP 中的协议段格式#xff0c;以及保证其可靠传输的重传机制#xff0c;着重介绍了三次握手建立连接#xff0c;四次挥手断开连接的过程(#x1f449;点击查看)。 这只是 TCP 保证通信可信策略的一部分#xff0c;现在让我们继续深入吧以及保证其可靠传输的重传机制着重介绍了三次握手建立连接四次挥手断开连接的过程(点击查看)。 这只是 TCP 保证通信可信策略的一部分现在让我们继续深入吧 流量控制
1. 流量控制的目的 一个报文千辛万苦现在到达了目的主机但是目的主机的缓冲区已经满了那只有对不起了只能把你丢弃了对于 TCP 协议来说我的报文已经发送了但是迟迟不见回应那是不是丢了呀我再发另一方说实在没位置了你发一个我只有丢一个网络资源就这样白白的浪费了这种情况应该避免 知道了问题我们就应该思考问题的本质为什么会这样怎样避免归根到底就是 发送方不知道接收方的接受能力导致的如果发送方能知道接收方的接受能力从而按照对方的实际接受能力发送的话就不会出现这种问题 这就是流量控制的目的。
2. 滑动窗口 在 TCP 协议段中有一个字段叫做 16位窗口大小这就是在告诉对方我现在的可以接受的空间是多少但是只有这个显然是不够的。咋们首先看一下滑动窗口到底是什么 好了本来对滑动窗口不熟悉的我看了这幅图就更懵了 首先我们需要理解 滑动窗口的窗口中维护的是需要发送的数据因为窗口大小是和对方的接受能力相关的 现在我想要提一个问题比如我现在发送了 22 这个报文那么我还得需要维护 22 嘛还是窗口向右滑动呢答案是还需要维护 22 只有收到了相应的应答报文才可以向右滑动。 起始从简单理解的话滑动窗口无非就是两个指针的移动为了更好地理解咋们来模拟一遍滑动的过程
左指针为 22代表窗口左边界窗口大小为 8 字节右指针为 29 代表窗口右边界现在将窗口的所有值发送收到 22 的应答报文返回的确认序号为 23 代表下一次的起始返回的窗口大小为 7。现在左指针指向 23右指针指向 29直接收到 26 的应答报文返回的确认序号 27下一次的开始返回的窗口大小为 3。现在左指针指向 27右指针指向 29。知识回顾为什么收到 26 的应答报文就直接更新了呢前面的 232425不管了吗这是因为应答报文的定义收到该应答报文就代表着该报文之前的数据也已经收到收到 28 的应答报文返回确认序号29下一次的开始返回的窗口大小为 5。现在左指针指向 29右指针指向 33。将新加入窗口的数据发送30 - 33
上述没有发生丢包的异常情况如果有也别担心会触发重传机制快重传 or 超时重传。
3. 窗口关闭问题 滑动窗口实现了发送方按需发送的能力但是还有一个问题。有没有可能出现接收方接收数据后应用层处理数据的速度太慢了导致缓冲区数据满了造成窗口大小最后返回 0 也就是窗口关闭的问题 对于这个问题接收方和发送方都有一定的策略
对于接收方TCP 为每个连接设有一个持续定时器只要 TCP 连接一方收到对方的零窗口通知就启动持续计时器。如果持续计时器超时就会发送 窗口探测(Window probe)报文而对方在确认这个探测报文时给出自己现在的接收窗口大小。当然如果多次探测之后窗口的大小还是 0 的话就会发送 RST 中断连接。对于接收方处理完数据后窗口自然而然增大了于是会向接收方发送窗口大小。
拥塞控制
1. 拥塞控制的目的 有了滑动窗口就极大避免了发送接收能力不对等的问题但是正常的发送接收数据还和网络的状态有极大的状态。就比如早上四五点的网络状态肯定是比起晚上七八点要好很多的。当网络拥塞时我们发送的数据包极有可能产生时延以及丢包问题这会导致我们再次重发加剧网络拥塞的状态。 拥塞的问题产生的原因就是网络上的数据包太多了负担太大了。TCP 为了避免这种情况使用了 拥塞窗口。
2. 慢启动 了解该算法之前我们首先得知道拥塞窗口是什么
发送开始的时候定义拥塞窗口大小为 1每次收到一个 ACK 应答, 拥塞窗口加 1每次发送数据包的时候将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较 小的值作为实际发送的窗口
现在了解了拥塞窗口我们就可以了解慢启动算法的具体过程了
发生拥塞时拥塞窗口的值变为 1 并且呈指数级别增长当到达一个门限时由指数增长变为线性增长再次发生拥塞时拥塞窗口变为 1 并且更新门限新的门限 发生拥塞时的窗口大小 / 2重复 1- 3 的过程
了解了大概的过程我们肯定心里也已经有了疑惑
为什么要将窗口变为 1并且采用指数增长为什么又要采用线性增长门限窗口的更新为什么是 发生拥塞时的窗口大小 / 2
问题一 发生拥塞时在网络上的负担已经很重了我们刚开始发送少数量的数据先让网络上的数据疏通之后在慢慢增加发送数据的量恢复正常的通信速度。慢启动只是 刚开始发送的数据少但是数据增加的速度可一点也不慢
问题二 如果一直采用指数增长的模式那发送的数据量就会非常大不出意外会快速的造成下一次拥塞的发生所以替换为指数增长。有人肯定会想不增长行吗一直维护在一个不会发生拥塞的大小。 网络的情况是一直在变化的 ! 正是因为如此才需要不断地增长去探测网络的承受能力。就比如七八点网络高峰期拥塞发生的频繁现在大家都维持在一个恰当的窗口大小来避免拥塞的发生。但是可能过了七八点到了凌晨的时候网络情况大大的缓和了但是我们的并没有继续线性探测来试探网络状态你还是以那个值作为窗口大小不就是浪费你的传输速率吗
问题三 在这里的介绍慢启动的很多解释明白了的很少。在这里我尝试用自己的理解来解释一下网络是变化的每一次发生拥塞时的窗口值都可能不一样但是前后相邻两次的差距可能不会很大所以当指数增长到上一次发生拥塞的值的一半时就不要指数增长了不然很可能再次拥塞让用户的网速像过山车一样一上一下一上一下。所以采取线性增长不断地试探新的拥塞触发点还可以让用户的网络情况尽量平稳一些。 面向字节流
1. 什么是面向字节流 我们在前面一直在提到 TCP 面向字节流UDP 是面向数据报。那么到底是什么个意思呢 首先我们先了解 面向数据报当我们使用 UDP 发送数据时该数据在传输层只会加一个报头然后交给下一层处理对方在 UDP 所读取的也是一个完整的报文然后交付给上一层。总而言之一个报文就是一次完整的发送数据。 TCP 是有一个真正意义上的缓冲区的当我们需要发送数据时会先将数据暂存在缓冲区至于多久发送取决 发送窗口、拥塞窗口以及当前发送缓冲区的大小等条件。就比如我想要发送两条信息Nihao! and How is going? 在底层的发送顺序可能是
Nihao | How is going?Nihao How is gong?Ni | hao How is gong?
所以我们不能简单认为 一个信息对应一个报文。面向字节流和面向数据报之间最大的区别就是 报文和报文之间有没有明确的边界。
2. 粘包问题 因为 TCP 是面向字节流的所以不可避免的报文和报文之间没有明显地边界那该怎么办呢TCP 并不负责这个所以需要我们在应用层来处理。
1. 定长消息 我们约定好我们一次传输报文的大小是多少字节然后只有接收方每次接收到指定字节大小数据那么就认为读取到了一次完整的报文但是这种方法不灵活。
2. 分隔符协议 发送方在每个数据包的结尾添加一个特定的分隔符接收方根据此分隔符进行拆包操作。
还有许多方法在这里就不介绍了。 总结 这篇文章中我们主要介绍了使用滑动窗口来控制流量拥塞窗口解决拥塞问题最后介绍了面向字节流希望大家有所收获