如何实现可靠的传输
rdt:要实现的可靠传输
udt:rdt所使用的底层的不可靠传输
-
rdt1.0-如果底层的通信完全无误
-
rdt2.0-如果底层的通信会产生位错误,(假设ACK和NCK通知不会产生错误)。则需要
-
错误检测(Error detection) : 校验和(Checksum)
-
接收反馈(Receiver feedback)发生ACK(Acknowledgment)和NAK给发送者,以指示是否成功接收信息
-
重发(Retransmission)
-
-
rdt2.1 如果底层的通信会产生位错误,(不假设ACK/NAK不会出错)。需要引入:
- duplicate packets:发送者可能会收到损坏的ACK/NAK报文段,无法知道接收者是否收到,重新发送该报文段。
- 引入序号(Sequence Number), 接收者通过检查序号来检查已经接收到的报文段是否被重发的。这里假设每次只会有一个报文段被传输,所以只需要0和1两个序号,就可以区分是重复的还是下一个应该接收的。(接收的0号,期待下一个为1号;接收到1号,期待下一个为0号)。(TCP的序号按字节数,而不是报文段的个数)
-
rdt2.2-如果底层的通信会产生位错误,(不假设ACK/NAK不会出错),且不再使用NAK,只有ACK
- (假设每次只会有一个报文段被传输,所以只需要0和1两个序号)
- 接收者收到报文段后返回携带着成功接收的最新的报文段的序号ACK给发送者
- duplicate ACKs:若发送者收到两个携带着相同序号的ACK(上一次发送的报文段的序号),则认为本次发生的报文段未被收到
-
rdt3.0 如果底层的通信会产生报文段丢失 和 位错误
-
因为报文段可能会丢失,发送者可能不能收到ACK。但发送者不能一直等待这个ACK。所以,在报文段发送出一报文段时间后还没有收到ACK,则认为其已经丢失,重新发送该报文段。
-
在rdt2.2的基础上加入倒计时的计时器(countdown timer):每当发送一个报文段后,启动开始倒计时;计时器归零后重发。
-
接收者的状态机与rdt2.2相同
-
流水线化 Pipelined
-
stop-and-wait:
-
pipelined:
-
同时发送多个报文段,而用等待一个报文段完成传输(收到ACK)再发送下一个
Go-Back-N(GBN) (Sliding-window protocol)
-
发送者:
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uBAFM00B-1641913456595)(gbn.png)]
- base: 最早的没有收到ACK的报文段
- nextseqnum :最小的没有发送的报文段
- [0, base - 1] :已经完成传输的报文段(ACK)
- [base, nextseqnum - 1] :已发送当未收到ACK的报文段
- [nextseqnum, base + N - 1] : 即将要发送的报文段
- N: Window Size 窗口大小
- 一次性将[nextseqnum, base + N - 1]内的报文段发出,不需等待ACK
-
接收者:
- 只接受其期待的下一个报文段(序号为expectedseqnum),其他的报文段直接丢弃
- 其回复的ACK携带其已经收到的最新的报文段的序号、
Selective Repeat(SR)
- 避免了Go-Back-N对大量报文段的不必要的重发。
- 发送者:
- 窗口内的每一个报文段都可以被单独标记为已ACK,而不用像GBN那样只接收窗口的第一个报文段的ACK(base)
- 每一个报文段都有其自己的逻辑的计时器,以在超时后重发该报文段。
- 接收到ACK后,将指定的报文段标记为已被接收的。如果这个报文段的序号为send_base,则可以推进窗口到最小的没有被确认的报文段的序号。
- 接收者:
- 接收到序号在其窗口范围[rcv_base, rcv_base+N-1]内的报文段,将其缓存,并对每一个接收到的报文段返回对应的ACK(不在像GBN那样只接收其期待的下一个报文段)。若接收到的报文段的序号为rcv_base,则可以推进窗口。
- 接收到序号在[rcv_base - N, rcv_base - 1]内的报文段:说明虽然该报文段已经被接收了,但发送者未收到ACK。需重新发送ACK。