内容提要:
-
RDT1.0
-
RDT2.0= RDT1.0 + 确认信息ACK or NAK
-
RDT2.1 = RDT2.0 + 发送包序号 + 确认信息ACK or NAK受损
-
RDT2.2 = RDT2.1 + 将NAK替换为ACK + ACK包序号
-
RDT3.0 = RDT2.2 + 超时重传定时器
状态表示:
[当前状态][动作注释]
发生的事件
TO
采取的操作[,...]
[到达的状态]
RDT1.0:完全可靠的信道数据传输
sender存在一种状态转换
[senderWating] ->[senderWating]
发完包接着去发下一个包
[senderWating]
rdt_send(data)
TO
packet = make_pkt(data),udt_send(packet)
[senderWating]
reciver存在1种状态转换:
[reciverWating]->[reciverWating]
接完包接着去接下一个包
[reciverWating]
rdt_rcv(packet)
TO
extract(packet,data),deliver_data(data)
[reciverWating]
RDT2.0:会出错的信道传输初级版
-
发送方发包后等待一个返回的ACK或NAK,若是NAK则保持停等状态继续发相同的包,继续等待;若是ACK则返回初始状态发送下一个包
-
接收方接受包检查包是否错误,如果有错误则将NAK信息打包,发回;如果没错误,则将包解析,将ACK信息打包,发回
sender存在3种状态转换:
[senderWating]->[sendWatingAckOrNak]
发完包准备接受对此包的确认包
[senderWating]
rdt_send(data)
TO
sndpkt = mak_pkt(data,checksum),udt_send(sndpkt)
[senderWatingAckOrNak]
[sendWatingAckOrNak]->[sendWatingAckOrNak]
接收到了否定确认 or 接收的确认包受损,继续重发
[senderWatingAckOrNak]
rdt_rcv(rcvpkt) and isNak(rcvpkt)
TO
rdt_send(sndpkt)
[senderWatingAckOrNak]
[sendWatingAckOrNak]->[senderWating]
接收到了肯定确认,转去发下一个包
[senderWatingAckOrNak]
rdt_rcv(rcvpkt) and isACK(rcvpkt)
TO
NULL
[senderWating]
reciver存在1种状态转换,两种动作
[reciverWating]->[reciverWating]
接到错误包,发送NAK包
[reciverWating][接到错误包情况]
rdt_rcv(rcvpkt) and corrupt(rcvpkt)
TO
sndpkt = make_pkt(NAK),udt_send(sndpkt)
[reciverWating]
[reciverWating]->[reciverWating]
接到正确包,发送ACK包
[reciverWating][接到正确包情况]
rdt_rcv(rcvpkt) and notcorrupt(rcvpkt)
TO
extract(rcvpkt,data),deliver_data(data),sndpkt = make_pkt(ACK),udt_send(sndpkt)
[reciverWating]
RDT2.1:ACK或NAK出错了该怎么办
-
发送方与前文RDT2.0的区别是:增加包序号位,发送方发包时附带包序号:此举为了让接受方明白发来的是新包还是一次重传;发送方接受反馈时,若是收到了损坏的NAK包,则不由分说进行一次重传
-
接受方与前文区别:接收方存在多个状态,对应于期望接收的包序号;接受坏包时,将发送NAK回发送方,直到发送方发送了正确的包过来,才跳转到下一个状态
sender发送一个包有2种状态,3种动作,如果发送多个包,他们的状态是相似的,所以此处只以发送一个包举例:
[senderWating0]->[senderWatingAckOrNak]
发送0号包,准备接收对0号包的确认包
[senderWating][发送0号包]
rdt_send(data)
TO
sndpkt = make_pkt(0,data,checksum) #增加包序号的发包
udt_send(sndpkt)
[senderWatingAckOrNak0]
[senderWatingAckOrNak0]->[senderWatingAckOrNak0]
接收到了NAK包 or 接收的确认包受损,重发包
[senderWatingAckOrNak][0号包确认]
rdt_rcv(rcvpkt) and (corrupt(rcvpkt) or isNAK(rcvpkt) )
TO
udt_send(sndpkt)
[senderWatingAckOrNak0]
[senderWatingAckOrNak0]->[senderWating1]
接收到ACK包,跳转准备发送下一个包
[senderWatingAckOrNak0]
rdt_rcv(rcvpkt) and isACK(rcvpkt) and notcorrupt(rcvpkt)
TO
NULL
[senderWating1][发送1号包]
reciver接收一个包有1个状态,3种动作,接收多个包的动作相似,只以接收一个包举例:
[reciverWating][sequence0] -> [reciverWating][sequence0]
接收0号包,接收出错,发回NAK包,继续准备接收0号包
[reciverWating][sequence0]
rdt_rcv(rcvpkt) and corrupt(rcvpkt)
TO
sndpkt = make_pkt(NAK,checksum),udt_send(sndpkt)
[reciverWating]
[reciverWating][sequence0]->[reciverWating][sequence0]
接收0号包,接收到1号失序包时,发送对1号包的ACK确认,强迫发送方从发送1号包状态跳转到发送0号包状态
[reciverWating][sequence0]
rdt_rcv(rcvpkt) and has_seq1(rcvpkt) and notcorrupt(rcvpkt)
TO
sndpkt = make_pkt(ACK,checksum)
[reciverWating][sequence0]
[reciverWating][sequence0]->[reciver][sequence1]
接收到正确的0号包,跳转准备接收1号包
[reciverWating][sequence0]
rdt_rct(rcvpkt) and notcorrupta(rcvpkt) and has_seq0(rcvpkt)
TO
extract(rcvpkt,data),deliver_data(data),sndpkt = make_pkt(ACK,checksum),udt_send(sndpkt)
[reciverWating][sequence1]
RDT2.2:将NAK替换为ACK,确认分组ACK包含了确认序号
-
发送方此时不再接收NAK,取而代之的是带有分组号的ACK;若是接收到了上一个接收的ACK序号,则重发当前包;若是接收到了期望接收的ACK序号,则跳转准备发送下一个包
-
接收方此时不再发送NAK,取而代之的是带有分组号的ACK;若是接收到了不是当前期望的包序号、错误的包;则发送对上一个接收的包的ACK信息,强迫发送方重发包;若是接到了正确的包,正确的序号,则跳转准备接收下一个包
sender发一个包具有2种状态,3种动作,多包动作相似:
[senderWating][sequence0]->[senderWatingACK]
[sequence0]
发送完0号包,准备接收对0号包的确认包
[senderWating][sequence0]
rdt_send(data)
TO
sndpkt = make_pkt(0,data,checksum),udt_send(sndpkt)
[senderWatingAck][sequence0]
[senderWatingAck][sequence0]->[senderWatingAck][sequence0]
发送方接收到了错误确认包 or 收到了对上一个包的确认
[senderWatingAck][sequence0]
rdt_rcv(rcvpkt) and (corrupt(rcvpkt) or isACK(rcvpkt, 1) )
TO
udt_send(sndpkt)
[senderWatingAck][sequence0]
[senderWatingAck][sequence0]->[senderWating][sequence1]
发送方接收到正确ACK包,且ACK确认的是当前期望的序号
[senderWatingAck][sequence0]
rdt_rcv(rcvpkt) and notcorrupt(rcvpkt) and isACK(rcvpkt,0)
TO
NULL
[senderWating][sequence1]
RDT3.0:ACK丢包之后的处理方法,带定时器;发送方负责监测和恢复丢包问题;增加了对包时延巨大的情况下的应对方案
-
发送方与上文的区别在于:发送方等待足够长的时间以确认包已经丢失,故将包重传;这个时间点确认应当选一个恰好的值
发送方发一个包具有2个状态,5个动作:
[senderWating][sequence0] ->[senderWating][sequence0]
发送方在准备发包时接到了包,什么都不做,扔掉;这就是时延巨大情况下的应对方案
[senderWating][sequence0]
rdt_rcv(sndpkt)
TO
NULL
[senderWating][sequence0]
[senderWating][sequence0]->[senderWatingAck][sequence0]
发送方发出了0号包,准备接收ACK包
[senderWating][sequence0]
rdt_send(data)
TO
sndpkt = make_pkt(0,data,checksum),udt_send(sndpkt),start_timer
[senderWatingAck][sequence0]
[senderWatingAck][sequence0]->[senderWatingAck][sequence0]
发送方接收ACK包超时,直接重传
[senderWatingAck][sequence0]
time_out
TO
udt_send(sndpkt),start_timer
[senderWatingAck][sequence0]
[senderWatingAck][sequence0]->[senderWatingAck][sequence0]
发送方接收对上一个包的ACK or ACK包受损,什么都不做直到计时器超时
[senderWatingAck][sequence0]
rdt_rcv(rcvpkt) and (isACK(rcvpkt,1) or corrupt(rcvpkt))
TO
NULL
[senderWatingAck][sequence0]
[senderWatingAck][sequence0]->[senderWating][sequence1]
发送方接收了ACK且对当前期望的包确认
[senderWatingAck][sequence0]
rdt_rct(rcvpkt) and notcorrupt(rcvpkt) and isACK(rcvpkt,0)
TO
stop_timer
[senderWating][sequence1]