可靠数据传输的原理
TCP是运输层的协议,向上层(应用层)提供面向连接的可靠的服务。而TCP的下层是网络层,网络层提供的尽力而为的服务,也就是说不提供任何质量保证。
那么TCP是如何在不可信信道上为上层服务提供可靠的服务呢?这里的可靠包括两方面:
- 传输的数据比特不会受到损坏或丢失。
- 所有数据都是按照其发送顺序进行交付的。
一、可靠服务的模型

如上图所示,运输层向应用层提供可靠数据传输服务。
运输层通过rdt_send()
函数,调用数据传输协议,把数据交付给接收方的运输层。发送方的运输层调用udt_send()
函数,将分组发送到不可靠的信道。
在接收端,当分组从信道的接收端到达时,将调用rdt_recv()
。当rdt
协议向较高层交付数据时,调用deliver_data()
完成。
二、 构造可靠的数据传输协议
我们将一步步地研究一系列协议,最后得到一个无错、可靠的数据传输协议。
1 经过完全可靠信道的可靠数据传输: rdt 1.0

上图是发送方和接收方的有限状态机,底层信道是完全可靠的。 发送方和接收方各只有一个状态。
图中的箭头指示了协议从一个状态变迁到另一个状态。引起变迁的事件在横线上方,事件发生时所采取的动作显示在横线下方。 FSM的初始状态由斜线表示。
2 经具有比特差错信道的可靠数据传输:rdt 2.0
底层信道肯定不是完全可靠的,下面我们考虑分组中的比特可能受损,但仍假设所有发送的分组将按其发送的顺序被接收。
接收方收到分组以后,可以向发送方发送肯定确认 (ACK) 或否定确认 (NAK) 。这些控制报文可以让发送方知道哪些内容被正确接收,那些内容接收有误并因此需要重复。这种基于重传的可靠数据传输协议被称为自动重传请求 (Automatic Repeat reQuest, ARQ) 协议。
ARQ协议需要三个功能来处理分组出错的情况:
- 差错检测
接收方需要检测到何时出现了比特差错。原理是通过增加发送方的冗余,如CRC校验等。 - 接收方反馈
接收方可以发送“肯定确认”或“否定确认”。 -
重传
接收方收到有差错的分组时,重传该报文。
如上图所示,发送方有两个状态。
当处于左边状态时,发送方等待来自上层传下来的数据。当上层调用rdt_send()
函数时,发送方产生带有校验和的分组,然后经由udt_send()
发送到到不可靠信道上。
在右边状态中,发送方等待接收方的ACK或NAK。如果收到ACK,那么发送方知道最近一个分组已经被正确接收,因此协议返回左边状态。如果收到NAK,那么发送方重传最近一个分组并等待接收方的ACK或NAK分组。
在上述协议中,当发送方处于等待ACK或NAK状态时,它不能从上层获得更多数据。这样子的协议被称为停等协议 (stop-and-wait)。rdt2.0
协议有一个致命的弱点,即没有考虑到ACK或NAK分组受损的可能性。
如果一个ACK或NAK受损,那么发送方无法判断接收方是否正确接收了上一个发送的分组。
处理受损的ACK或NAK的三种方法:- 增加控制信令。
即发送方请求接收方重复ACK或NAK分组。但新的控制信令也可能受损。 - 增加足够的校验和比特
使发送方不仅可以检测差错,还可以恢复差错。对于会产生差错却不会丢失分组的信道,可以直接解决问题。 -
重传当前数据分组
发送方收到损坏的ACK或NAK分组时,重传当前数据分组。这种方法在信道中引入了冗余分组 (duplicate packet)。 这导致接收方不知道接收到的分组是新数据分组的还是一次数据重传。
解决这个问题的方法是在所有数据分组中引入一个字段对数据分组编号,叫做序号 (sequence number) 。接收方只需要检查序号即可确定收到的分组是否是数据重传。对于停止等待这种情况,只需要 1 比特序号就够了。
我们把引入序号的协议称为rdt 2.1
,其发送方FSM图如下。
协议
rdt 2.1
使用了肯定确认和否定确认。当接收到正确的分组时,接收方发送一个“肯定确认”,当接收到受损的分组时,发送一个“否定确认”。
如果不发送NAK,而是对上次正确接收的分组发送一个ACK,也可以实现一样的效果。发送方如果接收到两个一样的ACK,就说明接收方没有正确接收到跟在被确认两次的分组后面的分组。
我们把只使用ACK的协议称为rdt 2.2
,其FSM图如下。

3 经具有比特差错的丢包信道的可靠数据传输: rdt 3.0
现在假定除了比特受损以外,底层信道还会丢包,这是一个常见的现象。
有很多可能的方法可以解决丢包问题,这里我们让发送方负责检测和恢复丢包工作。
假定发送方传输一个数据分组,该分组或者接收方对该分组的ACK发送了丢失。这两种情况下,发送方都收不到应当到来的接收方的响应。如果接收方愿意等待足够长的时间以便确认分组丢失,那么只需要重传该数据分组即可。
发送方需要等待多久来确认已经丢失了这个分组呢?很明显发送方应该至少等待发送方和接收方之间的一个往返时延和接收方处理一个分组的时间。
从发送端的观点来看,重传是一个万能灵药。为了实现基于时间的重传机制,需要一个倒数计时器 (countdown timer),在一个给定的时间量过期之后,可中断发送方。发送方需要做到:1)每次发送一个分组时,就启动一个定时器;2)相应定时器中断;3)终止定时器。
下图是rdt 3.0
的发送方FSM,该协议运行在可能发生出错和丢失的信道上。
 - 增加控制信令。
三、可靠数据传输协议的技术
校验和、序号、定时器、肯定和否定确认分组,这些技术都在协议的运行中起到了必不可少的作用。不过rdt 3.0
仍然是一个停止等待协议,效率不理想,没有有效利用信道的带宽。加入窗口、流水线技术可以提高信道利用率,也就初步模拟了TCP协议。

四、来源
- Kurose, KeithW.Ross, 库罗斯,等. 计算机网络:自顶向下方法[M]. 高等教育出版社, 2009.