数据可以通过一条可靠的信道进行传输,借助可靠信道,传输数据比特就不会受到损坏或丢失,且所有数据按照其发送顺序进行交付。
可靠数据传输协议的下层协议也许是不可靠的,可以将较低层直接视作不可靠的点对点信道。假设底层信道不会对分组重新排序,我们只可能丢失某些分组。
全双工数据传输:可靠的双向数据传输。下面考虑的都是单向数据传输,但是协议需要在发送端和接收端两个方向上传输分组。
构造可靠数据传输协议
经完全可靠信道的可靠数据传输:rdt 1.0
底层信道完全可靠-rdt 1.0
rdt1.0发送方和接收方的有限状态机FSM
,rdt1.0的发送方和接收方的FSM
都只有一个状态。
箭头指示了协议从一个状态变迁到另一个状态,由于只有一个状态,所以变迁必定是从一个状态返回到自身。引起变迁的事件写在横线上方,事件发生时采取的动作显示在横线下方。
rdt发送端:
- 通过
rdt_send(data)
事件接受来自较高层的数据,产生一个包含该数据的分组。 - 将分组发送到信道中
- 事实上
rdt_send(data)
事件是在较高层应用的过程调用产生的
rdt接收端:
- rdt通过
rdt_rcv(packet)
从底层接收一个分组,从分组中取出数据 - 将数据上传给较高层
- 事实上
rdt_rcv(packet)
是由较低层协议的过程调用产生的
在这个模型中接收端不需要提供任何反馈信息给发送方
经具有比特差错信道的可靠数据传输:rdt 2.0
分组中的比特可能受损,这种比特差错通常会出现在网络的物理部件中。
ACK
:肯定确认,positive acknowledgementNAK
:否定确认,negative acknowledgement,需要重复一遍
基于重传机制的可靠数据传输协议被称为自动重传请求协议 Automatically Repeat reQuest ARQ
ARQ协议还需要另外三种协议功能来处理存在比特差错的情况:
- 差错检测:使接收方检测到何时出现了比特差错。这些技术要求有额外的比特从发送方发送到接收方,被汇聚在rdt2.0数据分组的分组检验和字段中
- 接收方反馈:rdt2.0协议将从接收方向发送方会送
ACK
和NAK
分组,理论上这些分组只需要一个比特长,例如0表示NAK
,1表示ACK
- 重传:接收方收到有差错的分组时,发送方重传该分组报文
rdt 2.0的发送端:两个状态
- 左边的状态:
- 等待上层传下来的数据
- 产生
rdt_send(data)
事件时,发送方将产生一个包含待发送数据的分组sndpkt
,并且带有检验和 - 经由
udt_send(sndpkt)
操作发送该分组
- 右边的状态:
- 发送方协议等待来自接收方的
ACK
或NAK
分组 - 如果收到一个
ACK
分组,协议返回到等待来自上层的数据的状态 - 如果收到一个
NAK
分组,协议重传最后一个分组并等待接收方为响应重传分组而回送的ACK
和NAK
- 发送方协议等待来自接收方的
- 当发送方处于等待接收方发送
ACK
或者NAK
的状态时,不能从上层获取更多的数据,也即rdt_send(data)
事件不会发生
rdt2.0协议被称为停等协议 stop-and wait
rdt 2.0的接收端:一个状态
- 分组到达的时候要么回答
ACK
,要么回答NAK
,这取决于收到的分组是否受损
rdt2.0没有考虑到ACK
或者NAK
分组受损的可能,考虑如果一个ACK
或者NAK
分组受损处理的三种可能性:
- 发送方不理解
ACK
或者NAK
,要求接收方重新发送对应的报文,但是这个要求损坏 - 增加足够的检验和比特,使发送方不仅可以检测差错,还可恢复差错。对于会产生差错但不丢失分组的信道,可以解决问题。
- 当发送方收到含糊不清的
ACK
或者NAK
分组时,只需重传当前的数据分组。这种方法在发送方到接收方的信道中引入了冗余分组。无法事先知道接收到的分组是新的还是一次重传。
可以在数据分组中添加一个新的字段,让发送方对其数据分组编号,即将发送数据分组的序号放在该字段。接收方只需要检查序号就可以知道是否是一次重传。
rdt 2.1:发送端和接收端的状态翻倍
rdt 2.1 的发送端和接收端的状态数都是2.0的两倍,原因是协议状态此时必须反映出目前正发送的分组或希望接收的分组的序号是0还是1.
发送或期望接收0号分组的状态中的动作与发送或期望接收1号分组的状态中的动作是相似的,只有序号处理的方法不同
- 当接收到失序的分组时,接收方对所接受的分组发送一个肯定确认
- 如果收到受损的分组,接收方将发送一个否定确认
- 发送方接收到对同一个分组的两个
ACK
后,就知道接收方没有正确接收到跟在被确认两次的分组后面的分组
rdt 2.2
rdt 2.2是在有比特差错信道上实现的一个无NAK
的可靠数据传输协议:
- 接收方此时必须包括由一个
ACK
报文所确认的分组序号:这可以通过在接收方FSM
中,在make_pkt()
中包括参数ACK 0
或ACK 1
来实现 - 发送方此时必须检查接收到的
ACK
报文中被确认的分组序号:这可以通过在发送方FSM
中,在isACK()
中包括参数0或1来实现
经具有比特差错的丢包信道的可靠数据传输:rdt 3.0
假设底层信道会丢包。
让发送方负责检测和恢复丢包工作。假定发送方传输一个数据分组,该分组或者接收方对该分组的ACK
发生了丢失。这两种情况下发送方都收不到来自接收方的响应。
发送方可以等待足够长的时间以确定分组已经丢失,此时发送方重传数据分组即可。
- 至少需要等待发送方与接收方之间的一个往返时延加上接收方处理一个分组所需的时间
- 存在引入冗余数据分组的可能性:rdt 2.2使用序号来处理冗余分组情况
为了实现基于时间的重传机制,需要一个倒计数定时器,在一个给定的时间量过期后,可中断发送方。
发送方需要:
- 每次发送一个分组,包括第一次分组和重传分组时,便启动一个定时器
- 响应定时器中断
- 终止定时器
rdt 3.0 也被称为比特交替协议,分组序号在0和1之间交替
流水线可靠数据传输协议
rdt 3.0 的性能问题核心在于它是一个停等协议
定义发送方/信道的利用率为发送方:发送方实际忙于将发送比特送进信道的那部分时间与发送时间之比。
流水线技术:可以不使用停等方式运行,允许发送方发送多个分组而无需等待确认。
- 必须增加序号范围,因为每个输送中的分组必须有一个唯一的序号,而且也许有多个在输送中未确认的报文
- 协议的发送方和接收方两端也许必须缓存有多个分组。发送方最低限度应当能缓存已发送但是没有确认的分组
- 所需序号范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏以及延时过大的分组。
差错恢复的两个基本办法是:回退N步和选择重传
回退N步
回退N步(Go-Back-N,GBN)协议中,允许发送方发送多个分组(当有多个分组可用时)而不需等待确认,但它也受限于在流水线中未确认的分组数不能超过某个最大允许数 N N N
b a s e base base:基序号,定义为最早的未确认分组的序号
n e x t s e q n u m nextseqnum nextseqnum:下一个序号,最小的未使用序号,即下一个待发分组的序号
[ 0 , b a s e − 1 ] [0,base-1] [0,base−1]:段内的序号对应于已经发送并被确认的分组
[ b a s e , n e x e s e q n u m − 1 ] [base,nexeseqnum-1] [base,nexeseqnum−1]:段内对应已经发送但未被确认的分组
[ n e x t s e q n u m , b a s e + N − 1 ] [nextseqnum,base+N-1] [nextseqnum,base+N−1]:段内对应能用于那些即将要被发送的分组
大于或等于 b a s e + N base+N base+N 的序号不能使用,直到当前流水线中未被确认的分组,特别是序号为 b a s e base base 的分组已得到确认为止
随着协议的运行,窗口在序号空间内向前移动,GBN协议也被称作滑动窗口协议,流量控制是对发送方施加限制的原因之一
一个分组的序号承载在分组首部的一个固定长度的字段中。
如果分组序号字段的比特数是 k k k ,则该序号范围是 [ 0 , 2 k − 1 ] [0,2^k-1] [0,2k−1]。在一个有限的序号范围内,所有涉及序号的运算必须使用模 2 k 2^k 2k 运算,即将序号空间看为一个长度为 2 k 2^k 2k 的环。
GBN发送方必须响应三种类型的事件:
- 上层的调用。上层调用
rdt_send()
时,发送方首先检查是否有 N N N 个已发送但未被确认的分组。- 窗口未满,则产生一个分组并将其发送,并更新变量
- 窗口已满,发送方只需将数据返回给上层
- 在实际实现中,发送方更可能缓存(并不立刻发送)这些数据,或者使用同步机制允许上层在仅当窗口不满时才调用
rdt_send()
- 收到一个
ACK
。在GBN协议中,对序号为 n n n 的分组的确认采取累积确认的方式(接收到 n n n 及以前的分组) - 超时事件:定时器用于恢复数据或确认分组的丢失。如果出现超时,发送方重传所有已发送但还未被确认过的分组。如果收到一个
ACK
,但是仍然有已发送未被确认的分组,定时器会重新启动。如果没有已发送单位被确认的分组,定时器终止。
GBN接收方的动作:
-
序号为n的分组被正确接收到,并且按序,则接收方为分组n发送一个
ACK
,并且将分组中的数据部分交付到上层 -
其他情况下,接收方丢弃该分组,并为最近按序接收的分组重新发送
ACK
-
接收方丢弃所有的失序分组:接收缓存简单,不需要缓存任何失序分组。因此发送方必须维护窗口的上下边界以及
nextseqnum
在窗口中的位置,接收方需要维护的唯一信息就是下一个按序接收的分组的序号,保存在expectedseqnum
中
基于事件的编程:过程要么被协议栈中的其他过程调用,要么作为一次中断的结果
选择重传
在流水线中,单个分组的差错就能够引起GBN
重传大量分组。
选择重传(Selective Repeat,SR)协议通过让发送方仅重传那些它怀疑在接收方出错的分组而避免不必要的重传。这种重传要求接收方逐个确认正确接收的分组。依旧用 N N N 来限制流水线中未完成、未被确认的分组数。
与GBN不同的是,发送方已经收到了对窗口中某些分组的ACK
SR
发送方所采取的动作:
- 从上层收到数据:从上层接收到数据后,
SR
发送方检查下一个可用于该分组的序号。如果序号位于发送方的窗口内,则将数据打包并发送,否则要么缓存数据,要么返回给上层 - 超时:每个分组都有自己的逻辑定时器,因为超时发生后只能发送一个分组。
- 收到
ACK
:收到ACK
,如果该分组序号在窗口内,则SR
发送方将那个被确认的分组标记为已接收。如果分组的序号等于send_base
,那么窗口基序号向前移动到具有最小序号的未确认分组处。如果窗口移动了并且有序号落在窗口内的未发送分组,则发送这些分组。
SR
接收方将确认一个正确接收的分组而不管其是否按序。失序的分组将被缓存直到所有丢失分组皆被收到为止。
SR
接收方的动作:
- 序号在 [rcv_base,rcv_base+N-1]内的分组被正确接收。收到的分组落在接收方的窗口内,一个选择ACK被回送给发送方。如果该分组以前没收到过,就缓存该分组。如果该分组序号等于接收窗口的基序号,则说明该分组及以前缓存的序号连续的分组交付给上层。接收窗口按向前移动分组的编号向上交付这些分组
- 序号在[rcv_base-N,rcv_base-1]内的分组被正确收到,在这种情况下,必须产生一个ACK,如果没有产生ACK,那么发送方会重传分组,如果接收方不确认。那么发送方的窗口永远不会向前滑动。
- 其他情况,忽略该分组
发送方和接收方的窗口并不总是一致。
对于SR
协议来说,窗口长度必须小于或等于序号空间大小的一半。
总结
机制 | 用途和说明 |
---|---|
检验和 | 检测在一个传输分组中的比特错误 |
定时器 | 用于超时/重传一个分组。该分组或其ACK可能在信道中丢失。超时事件可能导致接收方收到一个分组的多个冗余版本。 |
序号 | 用于为从发送方流向接收方的数据分组按照顺序编号。序号间的空隙可以用来检测丢失分组,具有相同序号的分组可以用来让接收方检测分组的冗余版本。 |
确认 | 接收方用于告诉发送方一个分组或一组分组被正确接收了。确认报文通常携带着分组序号。 |
否定确认 | 接收方用于告诉发送方某个分组未被正确接收,报文通常携带分组序号 |