主机内部的传输数据被封装为“报文段”,而在主机之间,报文段加上了ip地址头部,我们称为“分组”,为了简便,我们简称为“包”。
1、总览
1.1 不可靠传输
什么叫不可靠传输?在传输中,在接收方可能出现以下问题:
问题 | 解决方案 |
---|---|
差错(包内部字节乱序,丢失等) | ACK与NAK反馈 |
乱序(包之间排序出现混乱) | ACK与NAK序号 |
冗余(重复传了同一个包) | 分组序号 |
丢包 | 倒计数定时器 |
1.2 可靠传输
- 通过各种手段解决了以上问题,就成为可靠传输了
- 可靠数据传输简称Rdt
2、差错
2.1 Rdt2.0
2.1.1 问题描述
如果传输过程出差错(指包内部位丢失,错位等),我们要做什么?
2.1.2 设计思路(Rdt2.0)
如果传输过程出差错(指包内部位丢失,错位等),我们要做什么?我们只能做,并且必须做两点:
- 接收方检测出差错,并告诉发送方
- 错了已经不能回头,只能重新传一次
2.1.2 ACK确认与ARQ协议
- 关键词:
校验和
,ACK与NAK重传
,停等协议
2.1.2.1 ACK确认与NAK重发
如果接收方成功收到分组,并且通过校验和判定这个包没出差错,就会回发一个“ACK”(positive acknowledgment)确认。如果检测出差错,就发送"NAK"(negative acknowledgment)
。- 发送方通过接收方的回复,判断发送是否出现了差错(收到回复之前他不会继续发),当收到ACK,就继续发下一个包,如果是NAK,就重发这个包。
Rdt2.0解决了差错问题,但是没有考虑ACK与NAK出现错误的情况
。
2.1.2.2 ARQ协议
这种具有自动重传机制的可靠数据传输协议称为ARQ(auto repeat reQuest)协议。在实现过程中,分为发送端与接收端,下面我们就分别探讨一下。
2.1.2.2.1 发送端
发送端的状态,有两种:
- 一种是发送状态,在这个状态中,上层可以调用rdt_send(data)方法指示其发送数据,并进入等待状态。发送端与接收端这两个状态是可以互转的。
- 另一种是等待状态,等待状态需要等接收端的回复,进而进入相应的处理流程(当收到ACK,进入到发送状态,继续发下一个包;如果是NAK,就重发这个包)。发送端与接收端这两个状态是可以互转的。
横线上面为调用该状态的方法,下面为该状态自己进行的方法 |
---|
2.1.2.2.2 接收端
注意此时是下层调用这个状态,因为接收端的数据是从下层往上层传的
横线上面为调用该状态的方法,下面为该状态自己进行的方法 |
---|
2.1.2.2.3 演示过程
- 没有错误:
红圈表示初始状态,data会加上checksum打包后发到接收端,发送端停等
,然后接收端发回ACK确认,发送方状态变化,一次发送执行完毕
- 出错
3、乱序与冗余
- 关键词:
序列号
,升级版ACK
3.1 Rdt2.1(添加序列号,解决包的乱序问题)
3.1.1 问题描述
- 如果ACK与NAK出错,那么发送方将会收到一个不可识别的确认消息
- 解决方法:重传
- 问题:导致发送的分组重复,产生冗余问题
3.1.2 设计思路
给分组加序号(0,1),接收方收到两个相同序号的分组时,抛弃后来的,同时要发ACK,让发送方知道,避免他重传
3.1.3 设计方案
- 加上校验和,状态翻倍;再加上序列号,状态再翻倍
- 接收方也是,分为希望收到0的状态和希望收到1的状态
3.2 Rdt2.2(使用升级版ACK,解决包的重传问题)
原来的NAK是为了告诉发送方我没收到某个分组
,现在用升级版ACK(也就是在ACK中加上确认的序列号)告诉发送方:“我已经收到了这个序列号的分组”,发送方下一次就知道要发别的分组了
总状态,上面是发送方,下面是接收方
4、丢包
- 关键词:定时器
4.1 问题描述
如果发送方发的包半路丢失,接收方不知道情况,导致发送方永远等下去
4.2 设计思路
很简单,设计发送方合理的等待时间,超过就重传
问题:包没有丢失,ACK延迟到达接收方导致了重传,就会产生冗余(不过我们Rdt2.2已经解决了问题)
4.3 设计方案
- a为正常发送
- b为发送方丢包,黑线为定时器时间,超过即重发
- c为接收方丢包(ACK丢失)
- d为ACK延迟,导致重发冗余
d最后收到了姗姗来迟的ACK1,但是他要的是ACK0,此时该怎么办?
(以后再解释)
5、性能
5.1 问题描述
从以上可以看到,停等协议使得发送方很多时间往往在等待,导致它的性能很差,比如:
我们可以直观感受下,下图中两个竖线之间的面积为可用网络资源,青色部分为用到的,所以性能很差,利用率仅为0.00027
5.2 流水线协议
5.2.1 使用流水线协议解决利用率低的问题
如下图,同时发3个就可以将性能提高3倍
5.2.2 带来的新问题:需要使用更多的分组序号
每多发一个分组,就必须多分配一个序列号,原来仅有0和1,现在需要更多的序号,为了解决这个问题,引入了滑动窗口协议(Go-Back-n(GBN)和 SR)