前言
我们都知道tcp的传输是可靠的,那么你知道tcp是如何实现数据的可靠传输的吗?今天就和大家一起探讨一下tcp是如何实现数据可靠传输的。
可靠传输的工作原理
我们知道网络传输是不可靠的,因为网络有着许多的不可控因素。那么要达成可靠的传输,我们需要满足以下两点。
1.数据能够准确传递到接收端
2.接收端处理数据的速度要能够跟上发送方发送数据的速度。
针对这两点,于是就有了停止等待协议。
什么是停止等待协议呢?
简单来说发送方在每次发送数据之后,必须要等到接收方的确认响应之后再继续发送后面的数据。很明显这样做虽然很简单,但是同样会带来一些问题。
问题一:发送方在发送完数据之后,需要一直等待接收方的确认答复。这样网络传输的效率非常低。
问题二:如果传输过程中有差错导致接收方没有接收到数据,那么接收端不会恢复确认,而发送方一直等待接收端的答复,那么就形成了死锁。
针对问题二,为了避免死锁的出现,于是有了超时重试机制。发送方会维护一个超时时间和一个信息的副本(用于重试,接收到确认信息后才删除),发送方发送完信息之后就会启动一个超时计时器,超时之后如果没有收到接收方的确认信息,那么就会重新再次发送。如果在超时时间内接收到了确认信息就撤销超时计时器。
这样死锁问题得到了解决,但是问题一的问题依旧存在,信道的利用率太低了,导致网络传输的速率太慢了。所以需要进一步优化。
于是就有了滑动窗口协议。而TCP正是基于滑动窗口协议来实现可靠传输的,所以我们重点分析滑动窗口协议。
滑动窗口协议
什么是滑动窗口协议?
将数据以字节为单位,并且为每个字节设置一个序号,并且发送端和接收端都需要维护一个窗口。
发送端:只有在发送窗口内的数据才可以被发送,发送窗口发送完数据之后需要等待接收端的确认,如果数据被确认之后,那么发送窗口就向右移动。
发送端滑动窗口示意图:
接收端:接收并且已经发送过确认消息的数据可以不用保存,只有在接收窗口内的数据才可以被接收。并且在接收端会维护一个期望收到的序列号(在图中也就是3),如果接收端接收到了4,5,6,但是没有接收到3,那么是不能够发送确认消息的。直到接收到序号3的数据,才会发送3,4,5,6的确认信息给发送端,然后将接收完的数据丢弃,并且向右移动接收窗口的预期接收序号值。
接收端滑动窗口示意图:
同样为了避免死锁,发送窗口协议同样有超时重发机制。
超时重发机制需要注意的是:接收端如果接收到一样的数据,那么可以直接丢弃数据,但是每次接收到数据,依旧需要发送确认接收消息给发送端。
很明显,滑动窗口协议相对于停止等待协议的信道利用率得到了很大的提高。
流量控制
前面我们提到了,接收端接收消息的速度一定要大于发送端发送消息的速度,不然就会导致接收端处理消息处理不过来,从而导致越来越多的消息超时,进而导致许多消息重发,这显示会降低我们的网络的传输效率。那么TCP是如何控制发送端的发送速度的呢?
接收端每次接收完消息之后,会发送一个报文将自己还能接收数据的窗口大小返回给发送端,如果还能接收数据的窗口大小为0,那么发送端是不能够继续发送消息的。
但是这样可能会出现一种极端情况:当接收端发送了零窗口的报文给发送端之后,接收端确认接收了100个数据,于是有了一些存储空间,于是又向发送端发送了一个100窗口的报文,但是不巧的是,刚好这个报文发送端没有接收到,那么就会导致发送端一直等待接收端的窗口报文,而接收端一直等待发送端发送消息,也就导致了死锁。
那么TCP是如何应对这种情况的呢?
为了解决这个问题,TCP为每个连接都设置了一个持续计时器,只要TCP连接的发送方收到了零窗口通知,那么就开启持续计时器,持续计时器的时间到了,就发送一个零窗口探测报文,而接收端接收到之后就回复当前最小的可接收数据的窗口值。
TCP的拥塞控制
什么是拥塞?在计算机网络中的宽带,交换节点中的缓存和处理机等网络资源不足,从而导致网络性能变差。简单来说就是资源的需求大于可用资源。
TCP怎么确定发生了拥塞?
TCP在发送端超时没有接收到接收端的确认消息就认为是出现了拥塞。
TCP拥塞控制的算法
慢开始算法
发送方维持一个叫做`拥塞窗口cwnd`的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口(注意还有流量控制的限制,所以发送窗口的值只能为拥塞窗口和可接收数据窗口之间的较小值)。
一开始设置cwnd的值为1,每次接收到确认消息之后cwnd翻倍,所以cwnd会呈指数变大。增加的速率会非常快,不能让cwnd无限制的指数增长下去,所以会有一个慢开始门限ssthresh。如果达到了慢开始门限,那么就会采用拥塞避免算法。
简单来说:
当cwnd < ssthresh,使用慢开始算法。
当cwnd > ssthresh,使用拥塞避免算法。
当cwnd = ssthresh,既可以使用慢开始算法也可以使用拥塞避免算法。
拥塞避免算法
拥塞避免算法的思路就是让cwnd缓慢的增长,每次收到接收方的确认消息,那么cwnd +1,让cwnd呈线性规律增长。
快重传算法
如果网络出现拥塞,那么就直接跳回到慢开始,会导致网络传输的速率突然变得特别慢。而且如果只是个别数据丢失,那么跳回到慢开始算法显得没有那么有必要,所以有了快重传算法。
举个例子:
发送端发送1,2,3三个数据给接收端,而接收端只接收到了1和3,没有接收到2,那么接收端需要对1进行重复确认,如果发送端收到三次重复确认,那么就知道2丢失了,就会马上重新传2过来。这就是快重传算法,不会因为个别数据丢失导致超时,从而跳回到慢开始算法,而是启动快恢复算法。
快恢复算法
将慢开始门限ssthresh和新的cwnd都设置为原cwnd/2,然后执行拥塞避免算法。
至此,关于TCP是如何实现可靠传输已经分析完了,相信大家对TCP的可靠传输已经有了一定的理解了。
最后
最后,如果有任何疑问,欢迎在下方评论区留言。