实现可靠数据传输(上)–原理篇

发布于 2021-09-19  63 次阅读


TCP协议提供面向连接的可靠数据传输,要想知道TCP是如何实现的,先要了解实现可靠传输需要哪些条件。

我们需要可靠数据传输协议这样的需求,是建立在通信的信道并不可靠的情况下的,下面就渐进式地引入不可靠因素,来逐步提出解决方案。

在描述传输过程的时候,通常使用有限状态机和状态转移图。

1、完全可靠的信道

在一个完全可靠的信道上,认为传输的信息不会出错,且一定会按顺序到达,此时就根本不需要可靠性协议,状态机如图:

Rdt 1.0:

发送方只管发,接收方只管收就行了。

2、会出现bit错误的信道

这种信道,在信息传输的中间过程可能会出现bit的翻转。

Rdt 2.0:

解决方法如下:

  • 首先是检测错误,引入校验机制,检查当前的数据是否有误。
  • 其次是引入错误恢复机制,即遇到错误之后怎么恢复数据的正常传输
    • 引入反馈确认机制:接收方接收到消息后,如果校验正确,发ACK确认包;若校验失败,发NAK反馈包
    • 引入重传机制:当发送方接收到NAK后,自动重传当前的包。

这就是所谓的 “停——等” 协议,状态机如下:

发送方在发完一个包之后,要等待接收方返回ACK/NAK来决定继续发送还是进行重传。


但 Rdt 2.0 也有自己的问题,如果回传的 ACK/NAK 包发生了错误咋办?

Rdt 2.1:

提出解决方案:

  • 首先同样是检测错误,在发送方引入校验机制,校验收到的ACK/NAK包。
  • 二是错误恢复
    • 当收到损坏的ACK/NAK,直接重传,这就叫做简单重传机制。

但是引入简单重传机制的时候,如果是 ACK 包出现错误,并重传的时候。接收端就会收到重复的包,这又要引入两个机制:

  • 包序列号:发送方对每个包标记序列号,在这种情况下,由于只对当前包和上一个包做判断,所以两个序列号就够用了。
  • 分组丢弃:接收方收到相同序列号的包之后,把重复的包丢弃

此时状态机如下:

发送方状态机
接收方状态机

Rdt 2.1 已经解决了传输中的问题,在其基础上,我们可以进一步修改,主要针对这样一个问题:

是否需要NAK包?毕竟少一种类型就少一种判断。

Rdt 2.2:

这种时候可以利用序列号,当发送ACK包的时候,带上最后一次正确接收的序列号。发送方通过比较序列号就能判断收到包是哪一个了!

改进后的状态机如图:

3、会出现bit错误和数据丢失的信道

前面的信道,不管包是否错误,包总是能够到达的。但实际上包可能出现丢失,这就是我们实际使用的网络环境,很糟糕吧?

前面的协议本质上都是 “停——等” 协议,即发送方需要等待接收方的响应。但在数据会丢失的信道上就不能这么做了。如果确认包丢失了,那么发送方就会一直等下去。这就需要新的解决方案:

Rdt 3.0:

  • 引入超时机制,即发送方等待一定的时间,如果超过这个时间,则认为包丢失了,进行重传。

实际上也是 “停——等” ,但因为数据包可能丢失,所以不一直等了。

执行过程如下:


到此,我们已经实现了一个可靠的传输协议,但其性能真的奇差无比,我们动手算一下。

示例:1Gbps链路,15ms端到端传播延迟,1KB分组

L = 1K * 8bit,R = 1G bit / s = 1Mbit / ms ==> t = 0.008 ms

RTT = 2 * 15ms = 30 ms;

在1Gbps链路上,完成一个包的发送需要30.008ms!实际速率仅 1k * 8bit / 30.008 ms = 0.267 Mbps

发送方利用率:发包时间0.008ms / 实际完成所需要时间30.008ms = 0.00027 即 0.027%。

这个协议对于信道的利用率实在太低了,下一章将会解析我们实际使用的TCP协议,看看它是如何在以上讨论的基础上提高效率的。


当其他人都认为你要鸽的时候,你鸽了,亦是一种不鸽