在网络状况不好的情况下,对于文件的传输,我们希望能够支持可以每次传部分数据。首先从文件传输协议FTP和TFTP开始分析,
FTP是基于TCP的,一般情况下建立两个连接,一个负责指令,一个负责数据;而TFTP是基于UDP的,由于UDP传输是不可靠的,虽然传输速度很快,但对于普通的文件像PDF这种,少了一个字节都不行。本次以IM中的文件下载场景为例,解析基于TCP的文件断点续传的原理,并用代码实现。
什么是断点续传?
断点续传其实正如字面意思,就是在下载的断开点继续开始传输,不用再从头开始。所以理解断点续传的核心后,发现其实和很简单,关键就在于对传输中断点的把握,我就自己的理解画了一个简单的示意图:
原理:
断点续传的关键是断点,所以在制定传输协议的时候要设计好,如上图,我自定义了一个交互协议,每次下载请求都会带上下载的起始点,这样就可以支持从断点下载了,其实HTTP里的断点续传也是这个原理,在HTTP的头里有个可选的字段RANGE,表示下载的范围,下面是我用JAVA语言实现的下载断点续传示例。
提供下载的服务端代码:
下载的客户端代码:
测试
原文件、下载中途断开的文件和从断点下载后的文件分别从左至右如下:
断点前的传输进度如下(中途省略):
Client fileLength : 51086228
finish : 0.020044541 %
finish : 0.040089082 %
finish : 0.060133625 %
finish : 0.07430574 %
finish : 0.080178164 %
...
finish : 60.41171 %
finish : 60.421593 %
finish : 60.428936 %
finish : 60.448982 %
finish : 60.454338 %
断开的点计算:30883840 / 51086228 = 0.604543361471119 * 100% = 60.45433614%
从断点后开始传的进度(中途省略):
Client startIndex : 30883840
finish : 60.474377 %
finish : 60.494423 %
finish : 60.51447 %
finish : 60.53451 %
finish : 60.554558 %
finish : 99.922035 %
finish : 99.942085 %
finish : 99.95677 %
finish : 99.96213 %
finish : 99.98217 %
finish : 100.0 %
finished!
断点处前后的百分比计算如下:
============================下面是从断点开始的进度==============================
本方案是基于TCP,在本方案设计之初,我还探索了一下介于TCP与UDP之间的一个协议:UDT(基于UDP的可靠传输协议)。
我基于Netty写了相关的测试代码,用Wireshark拆包发现的确是UDP的包,而且是要建立连接的,与UDP不同的是需要建立连接,所说UDT的传输性能比TCP好,传输的可靠性比UDP好,属于两者的一个平衡的选择,感兴的可以深入研究一下。