前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TCP是怎么实现可靠传输的

TCP是怎么实现可靠传输的

作者头像
Java进阶之路
发布2022-11-18 15:24:14
7130
发布2022-11-18 15:24:14
举报
文章被收录于专栏:分布式与微服务

前言

我们都知道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的可靠传输已经有了一定的理解了。

最后

最后,如果有任何疑问,欢迎在下方评论区留言。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-10-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java进阶之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档