android 限速工具,Android下载器之限速篇
发布日期:2021-06-24 11:17:48 浏览次数:4 分类:技术文章

本文共 1506 字,大约阅读时间需要 5 分钟。

0x01 前言

终于考完了马原完成了大学的最后一门考试,可以愉快的写代码了~今天就来记录一下我的下载器中是如何实现限速的。

0x02 限速的对象

市面上常见的专业下载器都会提供下载/上传限速这个功能,那限速究竟是限的哪一个速度呢?

我们都知道HTTP/HTTPS的传输层协议是TCP,TCP是基于字节流的。字节流在Java中对应的就是InputStream和OutputStream。基于TCP的传输层下载/上传的步骤一般是

建立TCP连接,对应Java的Socket.connect()。这期间会经历三次握手,是一个耗时过程,可以使用连接复用优化(OKHttp已经做了连接池缓存)。

连接成功后就可以根据需要收发数据,利用Socket获取到连接的InputStream和OutputStream操作即可。

关闭连接。

以下载为例,首先连接步骤是不需要限速的,因为连接部分通常是很快的,并且往往都想要连接更加快速。所以,我们限速的对象肯定就是从socket的InputStream这一步骤。

0x03 如何“限速”?

首先,这里的限速并不是真的限制读写数据流每时每刻的速度。这里要分清高中物理学过的两个概念——瞬时速度和平均速度。

equation?tex=s(t)

equation?tex=t时刻下载的字节,

equation?tex=v为下载速度则有:

equation?tex=v_%7B%E7%9E%AC%E6%97%B6%7D%20%3D%20%5Cfrac%7B%5Cmathrm%7Bd%7Ds(t)%7D%7B%5Cmathrm%7Bd%7Dt%7D

equation?tex=v_%7B%E5%B9%B3%E5%9D%87%7D%20%3D%20%5Cfrac%7Bs(t_2)%20-%20s(t_1)%7D%7Bt_2%20-%20t_1%7D

下载的瞬时速度和很多东西有关:硬件、网络状况、系统等,

equation?tex=s(t)是我们无法控制的。

但是有一个东西我们是,那就是

equation?tex=%5CDelta%7Bt%7D%20%3D%20s(t_2)%20-%20s(t_1)

我们下载的时候往往是在一个循环中不断的从网络读取数据到内存。我们可以在read之前记录时间

equation?tex=t_1,read操作之后记录时间

equation?tex=t_2。然后假设我们想要将下载的速度限制为

equation?tex=v_%7Bexpected%7D,那么,我们读取这段

equation?tex=%5CDelta%7Bs%7D字节的数据期望耗时为:

equation?tex=t_%7Bexpected%7D%20%3D%20%5Cfrac%7B%5CDelta%7Bs%7D%7D%7Bv_%7Bexpected%7D%7D

equation?tex=%5CDelta%7Bt%7D%20%3D%20t_%7Bexpected%7D%20-%20(t_2%20-%20t_1)

则当

equation?tex=%5CDelta%7Bt%7D%20%3E%200时,说明当前下载速度快,我们就可以调用Thread.sleep()这段时间,使得在宏观上下载的平均速度在我们的限制条件内。

另外,如果是多线程多任务,实际上平均分配速度即可。即任务间平均分配总速度,任务内线程平均分配任务获得的速度;

equation?tex=%5CDelta%7Bt%7D%20%5Cleq%200时是符合限制的。

0x04 代码实现

// 连接、获取输入流

...

int readSize;

long start;

do {

start = System.nanoTime();

readSize = inputStream.read(buffer, 0, buffer.length);

// targetBps是这个任务分配到的速度,targetBps < 0表示不限速

if (readSize > 0 && targetBps > 0) {

// downloadThreadCount是下载线程数

long sleepDurarion = (long) (readSize * 1000.0 / (targetBps / Math.max(downloadThreadCount, 1)) - (System.nanoTime() - start) / 1000_000.0);

if (sleepDuration > 0) {

try {

Thread.sleep(sleepDuration);

} catch (InterruptedException e) {

// do nothing

}

}

}

} while (readSize > 0);

复制代码

0x05 其他

上面主要是以下载为例,事实上任何I/O流的操作都可以通过这种方式在宏观上“限速”。

因为这种方法限制的是平均速度,所以如果装有网速监测软件,可能会看到波动的网络速度变化。

实现了限速功能的下载器项目传送门,支持多任务、多线程、多进程、断点续传、速度限制等等...

其他相关文章:

转载地址:https://blog.csdn.net/weixin_32459553/article/details/117311452 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:华为鸿蒙wifi6,运行鸿蒙OS!华为子母路由H6发布:再也不怕没WiFi了?
下一篇:deepin linux 2014安装,2014.2版本的Deepin虚拟机安装浅谈(就是深度Linux)

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月05日 02时41分19秒