再复述一下可靠性和有序性的含义
可靠性:
A节点发往B节点的包需要保证B节点一定能够收到
如果由于中间节点宕机或者其他问题导致丢包,需要由模块重发,直到B收到为止
有序性:
由于网络结构是图结构,一对节点间的通路可能有多条,这会导致连续发送的包不保证以同样的过程传过中间的网络。
A先后发给B节点packet1和packet2两个包,对B的上层应用来说要先感知packet1再感知packet2
如果实际上B先收到了packet2,需要等待packet1到达之后再转交给上层处理
其实受TCP协议耳濡目染,基本上很快可以想到一些朴素的做法,比如:包标识符(版本号)+ 队列 + 定时器
发送端发包:
1.记录发送的时间
2.把包放进发送包队列
只有在收到接收方的应答消息后才从队列中删除
如果过了一定的事件没有收到应答,这个包就需要重发,并把定时器复位
接收端收包:
记录期望收到的包的标识符nextID
如果当前包ID等于nextID,则立即回复一个应答消息给发送端
如果当前包ID大于nextID,则放入接收包队列,等待后续处理
如果当前包ID小于nextID,则丢弃
由于一个进程节点会对应多个远程节点,这要求:
每对节点都需要独立的发送包队列和接收包队列
每对节点都需要分配独立的包标识符
朴素做法最主要的问题有这几点:
1.每收到一个包都需要立即发送一个应答消息,带来了流量负担
2.重发依赖于发送端的定时器设置,时间断了可能导致重复发包多于实际需求,时间长了一旦发生丢包会有明显的延迟
针对这些问题有一些优化手段:
1.减少应答消息的发送次数
由于对接收方来说,收包处理是严格有序的,实际上可以不需要立即发送应答,只要周期应答最近处理的包。
对发送方来说,收到了一个应答包,就可以认为所有ID小于等于应答包ID的包都被收到了
2.接收方可以判断丢包并主动请求
当接收方收到的包ID大于期望的nextID时,很大程度上可以认为nextID这个包已经丢失了。
可以启动一个短暂的等待定时器,如果定时器触发后仍然没有收到nextID的包,则请求发送发重发,并启动一个重发定时器。
定时器会一直执行,直到收到正确的包为止
3.发送方定时方发送心跳包告知接收方当前待确认的标识符ID
这样可以保证如果最后发的一批包丢包了,接收方也能快速感知,并请求接收方重发
网友评论