0、可靠数据传输RDT
可靠数据传输在应用层、传输层、数据链路层都很重要;
是网络TOP10问题之一;
在网络层、物理层不重要?不是,应该是这两层有更侧重的方面,效率啥的;
图片备注:首先这个图是分层的,应用层、传输层及以下;
udt和rdt是对应的,rdt是可靠数据传输、udt是不可靠数据传输;
信道的不可靠特点,决定了可靠数据传输协议的复杂性,如何解决?
- 渐增式地开发可靠数据传输协议rdt的发送方和接收方;
- 双向数据传输是两个单向传输问题的综合,所以只考虑单向数据传输;(控制信息是双向流动的)
- 使用有限状态机FSM来描述发送方和接收方;(状态的变迁由事件组成,发生事件时要有哪些动作)
1、rdt1.0:在可靠信道上的可靠数据传输
特点:下层的信道是完全可靠的,没有比特出错;没有分组丢失;
FSM:
- 发送方:
- 状态1:等待上层的调用;有数据要发送rdt_send,封包make_pkt(data),利用下层udt发出数据,切换状态1;
- 接收方:
- 状态1:等待下层的调用,接收数据rdt_rev,解包extract,数据交给上层,切换状态1;
2、rdt2.0:具有比特差错的信道
特点:下层信道传输的数据可能会出错
措施:利用校验和来检测差错;如果出错,怎样从差错中恢复?
- 确认(ACK):接收方显式地告诉发送方,分组已被正确接收;
- 否定确认(NAK):接收方显式地告诉发送方,分组发生了差错,发送方收到NAK后重传分组;
要引入的机制:
- 发送方差错控制编码、保留副本;
- 接收方使用编码检错,反馈ACK或者NAK;
- 发送方根据反馈做出相应动作;
FSM:
- 发送方:
- 状态1:等待上层的调用;有数据要发送rdt_send,封包make_pkt(data,checksun),利用下层udt发出数据,切换状态2;
- 状态2:等待反馈;如果是NAK重发;如果是ACK,切换状态1;
- 接收方:
- 状态1:等待下层的调用,接收数据rdt_rev,校验对发送ACK,解包,交给上层,切换状态1;校验错发送NAK,切换状态1;
3、rdt2.1:处理出错的ACK/NAK
2.0的前提是数据可能出错,那如果ACK/NAK出错呢?
- 如果接受到火星语的ACK/NAK,需要重传,再等待反馈;
- 如果火星语是ACK,那么这个重复的分组将被丢弃;(如何知道重复?添加序号)
- 如果火星语是NAK,那么接收数据,解包,传给上层;
这个序列号只要0和1就足够了,只需要知道是新数据包还是旧数据包即可;
发送方:(左上角开始看)
- 状态1:等待上层的调用,要传数据,封包make_pkt(0,data,checksum)指明是数据包0,传输udt,切换状态2;
- 状态2:等待反馈0,如果是NAK或接收出错,重传数据包0;如果是ACK,切换状态3;
- 状态3:等待上层的调用,要传数据,封包make_pkt(1,data,checksum)指明是数据包1,传输udt,切换状态4;
- 状态4:等待反馈1,如果是NAK或接收出错,重传数据包1;如果是ACK,切换状态1;
接收方:
- 状态1:等待下层的数据包0:如果数据出错发送NAK;如果数据正确序号错发送ACK;如果数据正确序号正确发送ACK,切换状态2;
- 状态2:等待下层的数据包1:如果数据出错发送NAK;如果数据正确序号错发送ACK;如果数据正确序号正确发送ACK,切换状态1;
“如果数据正确序号错发送ACK”,这种情况就是上次ACK在发送过程中出错了,所以发送方又发了一遍,这时我们发送ACK是再次告诉发送方数据包收到了,以便发送方发下一组数据;(重新同步)
4、rdt2.2:无NAK的协议
功能与rdt2.1相同,但只使用ACK,为后面一次性传输多个数据做准备;
- 接收方接收分组后,发最后接收正确分组的ACK;
- 发送方收到重复的ACK就知道要重传,如果ACK校验错误也要重传;
- 发送方:
- 状态1:等待上层调用,要发送数据,封包make_pkt(0,data,checksum),发送数据包0,切换到状态2;
- 状态2:等待ACK;如果收到ACK1或错误ACK,重发;如果收到ACK0,切换状态等待发送下一个数据包;
- 接收方:
- 状态1:(从箭头方向看)如果收到正确的数据包1,解包,发送ACK1,切换到状态2;
- 状态2:等待下层调用,如果收到错误数据包 或者 仍然收到数据包1,发送ACK1(上一个正确的数据包);
5、rdt3.0:分组丢失的信道(超时重传)
- (a):没有丢失;
- (b):数据包在发送过程中丢失,超时重传;
- (c):应答在返回过程中丢失,超时重传;
- (d):不合理的超时时间设置;
过小的延时也能正常工作,但是效率低,发送分组、接收数据包、接收ACK应答都会重复;
过大的延时也会效率低,所以设置合理地超时时间很重要;
在发送数据包的时候开启定时器:
如果超时(没收到ACK)重发;如果收到错误的ACK或不是正确序号的ACK,也会导致超时重发;
如果正确接收到ACK,才会停止这一轮的定时器;
rdt3.0是停等协议,在链路容量比较大的情况下,效率很低;
例:带宽R为1Gbps的链路,15ms端到端的传播延时,分组大小L为1KB;
传输延时,T = L/R = 8000/10^9 = 8us;
信道信用率,U = T/(T+RTT)= 0.008/30.008 = 0.027%;
链路的吞吐量,1Gbps*0.027% = 270kbps;
流水线方式,不必等应答才发生下一个数据,如下图,可以连续发送3次数据,这样效率提高了3倍;
6、流水线协议
6.1、允许发送方在未得到接收方确认的情况下,一次发送多个分组
这就必须增加序号范围:用多个bit表示分组的序号;
6.2、发送方和接收方要有缓冲区
-
发送缓冲区的分组
- 未发送的:落入发送缓冲区,可以发但还未发的数据;
- 已发送的:等待对方确认,无误才能删除;
- 发送缓冲区大小:最多可以发送多少未经确认的分组;
- 接收方缓存:
- 上层取数据的速率可能小于接收到的数据速率;
- 接收到的数据可能乱序;
6.3、滑动窗口(slide window)协议
发送窗口:发送缓冲区的一个子集,指已发送未确认的分组;
- 每发送一个分组,前沿向前移动一个单位;
- 每得到最低序号分组的确认,后沿前移一个单位(不能超过前沿);
接收窗口 = 接收缓冲区,只有收到分组的序号在接收窗口内才接收,否则丢弃;
- 低序号分组到来,接收窗口滑动;
- 高序号分组到来,缓存但不向上层交付,不滑动;
发送窗口大小 | 接收窗口大小 | |
停止等待协议 | 1 | 1(只能顺序接收) |
回退N步(GBN) | >1 | 1(只能顺序接收) |
选择重传(SR) | >1 | >1(可以乱序接收) |
正常情况下,发送、接收窗口的互动;
发送窗口:
- 有新的分组落入发送缓冲区,发送,前沿滑动;
- 低序号分组确认,后沿滑动,使新的分组可以落入发送缓冲区;
接收窗口:
- 收到接收窗口范围内的分组,缓存,发送确认给对方;
- 低序号,窗口滑动;
异常情况下,GBN的发送、接收窗口互动
发送窗口:
- 新分组落入发送缓冲区范围,发送,前沿滑动;
- 超时重发机制,所有发送窗口中的分组全部发送;
- 来了低序号的分组重复确认,后沿不向前滑动,新的分组无法落入发送缓冲区;
接收窗口:
- 收到乱序分组,没有落入接收窗口范围内,丢弃,重复发送旧分组的确认(累计确认);
异常情况下,SR的发送、接收窗口互动
发送窗口:
- 新分组落入发送缓冲区范围,发送,前沿滑动;
- 超时重发机制,超时的分组重发;
- 来了乱序的分组确认,后沿不移动,新的分组无法落入发送缓冲区;
接收窗口:
- 收到乱序分组,没有落入接收窗口范围内,接收,发送该分组的确认(非累计确认);
6.4、GBN——回退N步协议
发送方发送0、1、2、3数据包,其中2丢失;
接收方收到0、1数据包,滑动窗口滑到2,等待接收2;
发送方收到0、1数据包应答,滑动窗口到2、3、4、5,此时4、5也被发送了;
因为2已经丢了,3到达,接收方仍然应答1,表示2没收到;
发送方超时都没收到2的应答,于是重新发送2、3、4、5;
GBN发送方:
一开始base = 1, nextseqnum = 1; 假设N = 3;假设上层只需要发送1、2、3数据包;
if(nextseqnum < 1+ 3), 发送数据包1(启动定时器1),nextseqnum++; 发送数据包2,3,此时nextseqnum = 4;
如果定时器超时,pkt1的确认还没有收到,重启定时器,重新发送1、2、3;(或者应答有误)
如果pkt1正确应答,base = 2,后沿滑动,但是2≠4,重启定时器,等待pkt2的返回;
如果定时器超时,pkt2的确认还没有收到,重启定时器,重发2、3;(或者应答有误)
如果应答pkt1,base = 2,后沿不滑动,仍然重启定时器,等待pkt2的返回;一直没等到,定时器超时重发2、3;
如果pkt2正确应答,base = 3,后沿滑动,但是3≠4,重启定时器,等待pkt3的返回;
如果定时器超时,pkt3的确认还没有收到,重启定时器,重发3;(或者应答有误)
如果pkt3正确应答,base = 4,后沿滑动,前沿=后沿,不发送也不等待应答,停止定时器;
GBN接收方:
这个图我觉得有点问题....(下面expectedseqnum简写为expect)
一开始,expect = 1,make_pkt封包准备了ACK1;
如果接受到正确的pkt1,解包发给上层,make_pkt封包ACK1,发送ACK 1,expect = 2,现在期望收到pkt2了;
如果下次收到不是pkt2,或校验有误,udt_send(sndpkt)会仍然发送发送ACK 1,这没有问题;
如果第一次收到的就是错误pk1,那么默认的"default"就会udt_send(sndpkt),即发送ACK 1;
这样在发送方,就会导致后沿移动,pkt1压根没收到也不会重发;
6.5、SR——选择重传协议
发送方对每个未确认的分组都要启动一个定时器,进行选择性重发;
发送窗口Ws > 1,存已发送的分组;
- 低序号分组确认到来,标记收到,停止定时器,后沿滑动;
- 高序号分组确认到来,标记收到,停止定时器;
接收窗口Wr > 1,可以接收的分组;
- 低序号分组到达,缓存,标记收到,发送该分组应答,滑动;
- 高序号分组到达,缓存,标记收到,发送该分组应答,不滑动;
发送方发送0、1、2、3共4个分组,启动这4个定时器,pkt2丢失;
发送方收到0、1的确认,由于是最低序号,发送窗口可以向前滑动,到2、3、4、5;此时4、5分组也被发送;
发送方等到pkt2超时也没有收到确认,重发pkt2,再次启动定时器;
发送方收到3、4、5确认,但是2的确认没有来,发送窗口不能滑动;
接收方收到pkt3、4、5,但是pkt2没有收到,接收窗口也不能滑动,等2到了,接收窗口滑动到6、7、8、9;
6.6、GBN和SR的对比
GBN | SR | |
特点 | 简单,接收方仅需一个缓存单元 | 复杂,接收方所需多个缓存单元 |
出错时,回退N步代价大 | 出错时,重传一个代价小 | |
选择 | 出错率低时,可以选择GBN | 出错率高时,选择SR (GBN会重传多个) |
链路延时大:选择SR (GBN一旦乱序,就白传了) |