tcp-可靠传输的原理

TCP报头

网络-tcp报文段首部结构这篇博客中,介绍了tcp的报文头结构,本文介绍tcp的可靠传输如何实现及与报文头结构的关系。报文头如下:

tcp可靠传输概述

tcp可靠传输的原理是什么?重传。

同步传输:哪些情况下会重传

  1. 包丢失,导致发送方一直没收到接收方的回包
  2. 包损坏,接收方返回NAK,或者接收方的回包本身被损坏(需要用到TCP报头第五行的16位校验和字段来判断是否损坏)

同步传输:如果是因为回包失败,那么会重复发包,如何去重

给包加上编号01,用来区分前后两个包。接收方返回的ACK包里面包含是哪个包的ACK信息,这里采用接下来期望哪个包来表达(为啥?),如果接收端已经正确收到0包,此时在收到一个0包,则忽略这个新的0包,返回ACK(1),那么发送方接下来就知道发送1包。有了包编号,就可以将上面提到的NAK给去掉,用ACK来表达:比如0包损坏,就返回ACK(0);否则返回ACK(1)。这里将包损坏和包重复两种情况合并了,这两中情况的结果都是让发送方在发一个包,只不过是发送包的编号不同(ACK里面的参数是下一次期望接受的包的编号)。

同步传输太慢,如何改为异步传输(并发传输)

那就是一次要传输多个包。

扩充编号

  • 首先多个包需要区分,原来用01编号不行,那就用一个更大的序号编号,即TCP报头第二行的32位序列号。这样看,只需要一个序列号字段就可以了,发送方序列号里面存本次发送的包的编号,接收方的回包里面存下次期望收到的编号,这样看起来也行啊?需要注意的是,这样需要区分发送方和接收方,是一个单工协议,只能单方面专递消息;而TCP是一个双工协议,所以需要序列号和确认号两个号码:序列号里面存储本次发送的包的编号,确认号里面存储期望从对方那里收到的下一个包的编号。序列号和确认好分别位于TCP报头的2、3行,各32位。

并发度为多少:一次可以发多少个包

  • 发送方一次最多可以发多少个包这个值称为滑动窗口长度,存储在TCP报头的第四行后16位;当前能发的包的范围成为滑动窗口,包括已发送未收到ACK有可能要重发的、能发送还未发送的这两种。滑动窗口长度即tcp报头第四行后16字节里面存的值主要是用来限流的,但是滑动窗口本省确实用来进行可靠传输的。

乱序到达的包接收端怎么处理以及对应的发送端如何重传

  • 多个包有可能乱序到达,接收端有两种选择:一种是将非本次期望的包给丢弃,这样虽然发送端是并行的,但是接收端是串行的,而且这样乱序到达的包都是不必要的,会浪费传输资源;另一种是将乱序到达的包缓冲起来,每个包插入到其对应的位置,将低水位的包链(从期望包开始一段连续没有空缺的包)传递给引用层。那么,TCP使用的是那种方式呢?
    • 对于缓冲了的情况,只需要把缺失的包补齐即可,所以就是选择重传。选择重传因为会缓冲分组,数据并没有丢失,为了避免发送方超时重复发送,所以每收到一个分组就返回一个ACK,但是发送方只有收到最开始的那个ACK才能移动滑动窗口。因为每个都会返回ACK,那么如果没收到ACK的包就是真超时了,需要重传,这需要为每个包设置一个计时器。
      选择重传的发送方
      选择重传的接收方
      接收方对于收到[rcvbase-N,rcvbase-1]的包,有可能是前面的包的ACK超时,所以也需要回ACK,不然发送方滑动窗口的不能移动。
    • 对于没缓冲的情况,如果有一次乱序到达,此时乱序到达的都被丢弃,是需要从下一个ACK开始重传所有包的。如果每个接受的包都会一个ACK,那么将造成大量不必要的传输,此时接收方选择累计ACK会比较好。由于是整批发送,所以只需要设置一个计时器就可以了。
      go-back-n

滑动窗口大小问题

  • 对于go-back-n,这里有个问题,假设序列号是k位,那么 可以有2^k中序号(0……2^k -1),假如说发送方的将这2^k次方个序列号都使用,极端情况下,0到2^k-2号的ACK都丢失,只有2^k -1的ACK到达(ACK(0)),这之前发送方检测到0包超时,重发了一个0包,此时接收端如何区分这个0包是新一轮的0包还是发送方重传的0包呢?解决办法是让同时并发发送的包的个数小于2^k,即最大为2^k-2,此时会返回ACK(2^k-1),接收方看到不是自己期望的包(2^k-1),会将0包丢弃。即并发发送包的数量要小于2^k,最大值为2^k-1。这个并发发送包的数量称为发送方滑动窗口的大小,在TCP报头的第4行的右边16个字节,(2^16<2^32)。
    go-back-n滑动窗口大小
  • 对于选择重传:
    选择重传滑动窗口大小

猜你喜欢

转载自blog.csdn.net/u013319359/article/details/81143212