关于使用不可靠的UDP实现可靠传输
整理本Log希望日后有时间可以实现定制化的UDP协议,很多情况即想要UDP的部分特性,又希望UDP在接受范围内尽量稳定,如果可以实现一个相对通用的类库实现此类需求将大大简化。(重复造轮子)
以下是常见的保证UDP传输稳定手段,可以根据需求自行选择实现部分,全部实现就相当于在应用层重新实现一遍TCP。
1、超时重传
2、有序接受
3、应答确认
4、滑动窗口流量控制
(一)发送机制
首先来设计最为重要的可靠性。在UDP增加报头前,我们先定义8个字节的协议头,为2个字节的数据包标识,2个字节的发送序号,2个字节的文件指针定位和2个字节的数据包中数据大小信息。数据包标志指明该数据包为文件数据包、确认包或者其它控制包,发送序号用来指明数据包的顺序信息,指针定位字节数据用来指明该数据包中数据被填写到文件的哪个位置,最后的大小信息也是用来向文件中读写数据时使用。
发送大致流程:
这里我考虑的是:继承QUdpSocket,重新实现write接口。这里两种情况,简单情况下尽量只让接收方发送一次错误信息回发送方,不做重传。复杂情况则每个分包都需要接收方返回确认接收信息,如未收到则重新发送
int writeMessage(MessageType type,QString data)
{
head = type + sendNumber + packgeNumber + dataSize
//type指明发送数据类型文件还是信息
//sendNumber用于数据被分为几个小包
//packgeNumber当前是第几个包
//dataSize信息大小
write head+data
}
(二)接收机制
1、简单情况下:
接收端收到全部数据包和结束包后,按照包头错序重排,接受过程只要保证序号从小到大即可,反之不是则出现错误。
2、高可靠情况下:
文件信息包被接收端接受以后使用确认机制确定是否接受这个文件,并把决定回馈给发送端。此时,发送端如果收到的是“确定接受”的结果,将会把这个文件的整组数据报全部发送过去。
这里我们不像最传统的可靠传输协议TCP协议一样,对于每个每个报文都要确认接受完才会对下一个报文进行处理。接受端在接受这组报文的时候将遵守错序重排机制,接受过程只要保证序号从小到大即可,反之不是则出现错误,向发送端回复错误包序号。
发送端发完所有报文延迟一点时间再发送一个结束报文,延迟时间是为了减少结束报文比数据报文还早被接受的情况,当然即使这种情况出现也不会破坏可靠性,只不过在在结束报文之后的数据报文会被当做丢失的包被要求重发,降低效率。接受端接受到结束报文后按照一开始的文件信息包的信息和序列号做对比,把没有的序列号的报文的信息传回给发送端,要求重新发送这些报文。发送端接到信息以后重发丢失的数据包。直到接收端拿到的报文和信息匹配,接受端就可以发回一个“接受完毕”的报文。这样发送端接受端再进行下一次文件传输。
具体自动重发机制、请求重发机制、确认机制日后实际实现时补充。