前导内容:状态机的表示方法
[当前状态][状态描述]
动作描述
TO
具体操作法
[到达状态][状态描述]
知识点一览:
概述:多个包发完之后,由于ACK延迟的原因,有多个包暂未得到ACK;若是等待的第一个未经确认的包超时,由以下两个协议决定重发所有未经ACK的包或只发最前的未经ACK的包
-
goBackN协议
-
selectRetransmit协议
goBackN协议
第一步没说的,上状态机:goBackN具有1种状态,4种动作,base最小未确认分组包,nextsequence下一个待发送包 , N允许同时存在的发送但未经确认的包
[发出数据包0,准备发送下一个包1]
[senderWating][noTimer]
rdt_send(data)
TO
if nextseqnum is in aviliable range: #
sndpkt[nextsequence] = make_pkt(nextseqnum,data,checksum)
if base == nextseqnum:
start_timer
nextseqnum++
else:
refuse_data(data)
[senderWating][timerStart]
[等待的第一个未经确认的包超超时]
[senderWating][timerOut]
timeout
TO
start_timer
udt_send(sndpkt[base])
udt_send(sndpkt[base+1])
udt_send(sndpkt[base+2])
……
[senderWating]
[接到错误包,等待计时器超时]
[senderWating][timerStart]
rdt_rcv(rcvpkt) and corrupt(rcvpkt)
TO
NULL
[senderWating][watingTimerOut]
[接到期望的第一个包的ACK信息,如果未经确认的包已确认完,则停止计时器,若依然存在,则重启计时器]
[senderWating][timerStart]
rdt_rcv(rcvpkt) and notcorrupt(rcvpkt)
TO
base = getacknum(rcvpkt) +1
if base == nextseqnum:
stop_timer
else:
start_timer
[senderWating][timerRestart]
selectRetransmit协议
与goBackN协议相似,但是此时发送方的各包都有自己的计时器,发送方接受方均有长度为N的窗口长度,具体如下:
发送方:
- 从上层收到数据,如果次包在发送方可发送的最多未确认的包范围内,则发送,若不在范围内,则返回给上层以便下次发送时调用
- 如果单个包接收ACK时间超时,则重传分组
- 收到ACK,如果此包的序号为最小的未确认序号,则将sendBase设置为最小未确认分组号
接收方:
- 序号在接收窗口内被正确接收,返回次窗口的ACK信息给接受方,如果接到的分组号与rcvBase相同,则将从rcvBase开始的一堆连续的分组向上提交
- 接收到了已经接收过的分组,则重新发送一份ACK包给发送方,强迫发送方滑动发送窗口
- 其他情况,忽略该分组