从0开始http之旅-2-TCP可靠性传输的实现

更多精彩好文关注
golang技术实验室

TCP可靠传输的实现

字节为单位的滑动窗口

TCP的滑动串口是以字节为单位的,我们暂且嘉定只是A收到B发来的确认报文段,其中窗口是20字节,而确认号是31(这表明B期望收到的下一个序号是31),
而序列号是30为止的数据已经收到,根据这两个数据,A就构造出自己的发送窗口,如图

在这里插入图片描述

先看发送方A的发送窗口,发送窗口表示,在没有收到B的确认的情况下,A可以连续把窗口内的数据都发出去,凡事已经发送过的,在未收到确认之前都要保留,以便在超时重传时候使用。

发送窗口里面的序列号表示允许发送的序号,显然,窗口越大,发送方接可以在收到接收方确认之前连续发送更多的数据,因而获得更高的传输效率,而接收方也会在发送确认的窗口中表明自己的接收窗口数值,因此A的发送窗口大小一定不能超过B的接收窗口

发送窗口的后沿的后面部分表示已经发送且已经收到了确认,这些数据显然不需要在保留,而发送窗口前沿的部分表示不允许发送的,因为接收方没有为这部分数据保留临时存放的缓存空间

发送窗口的位置由窗口前沿和后沿的位置共同决定,发送窗口后沿的变化情况有两种可能,即不动(没有收到新的确认)和前移(收到了新的确认)。发送窗口后沿不可能向后移动,因为不能撤销已经收到的确认。

发送窗口前沿通常是不断向前移动,但也有可能不动,这对应两种情况:一是没有收到新的确认,对方通知的窗口大小也不变;二是收到了新的确认但对方通知的窗口缩小了,这使得发送窗口前沿不动

发送窗口的前沿有可能向后收缩,这发生在对方通知滑动窗口缩小了,但TCP的标准强烈不建议这样做,因为很可能发送方在收到这个通知以前已经发送了窗口中的许多数据,现在又要收缩窗口,不让发送这些数据,会产生错误

现在假定A发送了序号为31~41的数据,这时,发送窗口位置并未改变,但是发送窗口内靠后的11字节(黑色部分)表示已经发送但未收到确认,而窗口内靠前的9个字节(42-50)是允许发送但为发送方成功的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W8qqD1DA-1614935414726)(geekTime-http.assets/image-20210305104347625.png)]

从以上所述可以看出,要描述一个发送窗口的状态有三个指针:P1、P2、P3。指针都指向字节的序号。指针的含义:
小于P1的是已发送并已接收到确认的部分,而大于P3的部分是不允许发送的部分
P3-P1=A的发送窗口
P2-P1=已发送单位但未收到确认的字节数
P3-P2=允许发送当前尚未发送的字节数(又称为可用窗口或有效窗口)

在看下B的接收窗口,B的接收窗口大小为20,在接收窗口外面,到30号为止的数据是已经发送确认,并且交付主机的,因此在B可以不保留这些数据。接收窗口的(31-50)是允许被接收的,B接收到32和33这些数据,这些数据没有按序到达,因为序号为31的数据没有收到(也许丢了秒也许滞留在网络中),B只能对按序收到的数据的最高序号给出确认,因此B发送的确认报文段最大的序号是31

现B收到了序号为31的数据,并把序号31-33的数据交付主机,然后B删除这些数据,接着把接收窗口向前移动3个序号,同时给A发送确认,其中窗口值仍为20,但确认好是34,
这表明B已经收到了到序号33为止的数据。我们注意到,B 还收到了序号为37, 38和40的数据,但这些都没有按序到达,只能先暂存在接收窗口中。

A到B的确认后,就可以把发送窗口向前滑动3个序号,但指针P2不动。可以看出,现在A的可用窗口增大了,可发送的序号范围是42〜53。

在这里插入图片描述

A在继续发送完序号42 ~ 53的数据后,指针P2向前移动和P3重合。发送窗口内的序 号都巳用完,但还没有再收到确认(图)。由于A的发送窗口巳满,可用窗口已减小到 零,因此必须停止发送。

请注意,存在下面这种可能性,就是发送窗口内所有的数据都已正 确到达B, B也早已发出了确认。但不幸的是,所有这些确认都滞留在网络中。在没有收到 B的确认时,A不能猜测:“或许B收到了吧!”为了保证可靠传输,A只能认为B还没有 收到这些数据。

于是,A在经过一段时间后(由超时计时器控制)就重传这部分数据,重新 设置超时计时器,直到收到B的确认为止。如果A收到确认号落在发送窗口内,那么A就 可以使发送窗口继续向前滑动,并发送新的数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qDDFFvlg-1614935414744)(geekTime-http.assets/image-20210305110540167.png)]

我们在前面的图中曾给出了这样的概念:发送方的应用进程把字节流写入TCP的 发送缓存,接收方的应用进程从TCP的接收缓存中读取字节流。下面我们就进一步讨论前 面讲的窗口和缓存的关系。图画出了发送方维持的发送缓存和发送窗口,以及接收方 维持的接收缓存和接收窗口。这里首先要明确两点:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BmDPhH0p-1614935414746)(geekTime-http.assets/image-20210305110716326.png)]

第一,缓存空间和序号空间都是有限的,并且都是循环使用的。
第二,由于实际上缓存或窗口中的字节数是非常之大的,因此图仅仅是个示意 图,没有标出具体的数值。但用这样的图来说明缓存和发送窗口以及接收窗口的关系是很清 楚的。
我们先看一下图(a)所示的发送方的情况。
发送缓存用来暂时存放:

  1. 发送应用程序传送给发送方TCP准备发送的数据;
  2. TCP己发送出但尚未收到确认的数据。

发送窗口通常只是发送缓存的一部分。已被确认的数据应当从发送缓存中删除,因此 发送缓存和发送窗口的后沿是重合的。发送应用程序最后写入发送缓存的字节减去最后被确 认的字节,就是还保留在发送缓存中的被写入的字节数。发送应用程序必须控制写入缓存的 速率,不能太快,否则发送缓存就会没有存放数据的空间。

再看一下图(b)所示的接收方的情况。
接收缓存用来暂时存放:

  1. 按序到达的、但尚未被接收应用程序读取的数据;
  2. 未按序到达的数据。

如果收到的分组被检测出有差错,则要丢弃。如果接收应用程序来不及读取收到的数 据,接收缓存最终就会被填满,使接收窗口减小到零。反之,如果接收应用程序能够及时从 接收缓存中读取收到的数据,接收窗口就可以增大,但最大不能超过接收缓存的大小。图 (b)中还指出了下一个期望收到的字节号。这个字节号也就是接收方给发送方的报文段的 首部中的确认号。

根据以上所讨论的,我们还要再强调以下三点。

第一,虽然A的发送窗口是根据B的接收窗口设置的,但在同一时刻,A的发送窗口 并不总是和B 的接收窗口一样大。这是因为通过网络传送窗口值需要经历一定的时间滞后 (这个时间还是不确定的)。另外,发送方A还可能根据网络 当时的拥塞情况适当减小自己的发送窗口数值。

第二,对于不按序到达的数据应如何处理,TCP标准并无明确规定。如果接收方把不 按序到达的数据一律丢弃,那么接收窗口的管理将会比较简单,但这样做对网络资源的利用 不利(因为发送方会重复传送较多的数据)。因此TCP通常对不按序到达的数据是先临时存 放在接收窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程。

第三,TCP要求接收方必须有累积确认的功能,这样可以减小传输开销。接收方可以 在合适的时候发送确认,也可以在自己有数据要发送时把确认信息顺便捎带上。但请注意两 点。一是接收方不应过分推迟发送确认,否则会导致发送方不必要的重传,这反而浪费了网 络的资源。TCP标准规定,确认推迟的时间不应超过0.5秒。若收到一连串具有最大长度的 报文段,则必须每隔一个报文段就发送一个确认[RFC 1122]。二是捎带确认实际上并不经常 发生,因为大多数应用程序很少同时在两个方向上发送数据。

最后再强调一下,TCP的通信是全双工通信。通信中的每一方都在发送和接收报文 段。因此,每一方都有自己的发送窗口和接收窗口。在谈到这些窗口时,一定要弄清是哪一 方的窗口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

a...Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值