Java程序如何限速(控制下载和上传速度)
转自 http://www.blogjava.net/canvas/articles/bandwidthlimiter.html
思路很简单,如下:
1.假设下载或者上传速度上限是m (KB/s),那么发送一个固定的字节数据(假设是n字节)的时间花费是:n/m;
2.假设现在要发送n字节的数据,那么理论所需的时间应该是n/m,而在实际情况下,发送n字节的数据只花费了t秒,那么发送该发送线程就应该睡眠n/m-t秒,这样就基本实现了速度的控制。
代码以TCP为例
速度控制
2
3 /**
4 *
5 * @author Le
6 *
7 */
8 public class BandwidthLimiter {
9
10 /* KB */
11 private static Long KB = 1024l;
12
13 /* The smallest count chunk length in bytes */
14 private static Long CHUNK_LENGTH = 1024l;
15
16 /* How many bytes will be sent or receive */
17 private int bytesWillBeSentOrReceive = 0;
18
19 /* When the last piece was sent or receive */
20 private long lastPieceSentOrReceiveTick = System.nanoTime();
21
22 /* Default rate is 1024KB/s */
23 private int maxRate = 1024;
24
25 /* Time cost for sending CHUNK_LENGTH bytes in nanoseconds */
26 private long timeCostPerChunk = (1000000000l * CHUNK_LENGTH)
27 / (this.maxRate * KB);
28
29 /**
30 * Initialize a BandwidthLimiter object with a certain rate.
31 *
32 * @param maxRate
33 * the download or upload speed in KBytes
34 */
35 public BandwidthLimiter(int maxRate) {
36 this.setMaxRate(maxRate);
37 }
38
39 /**
40 * Set the max upload or download rate in KB/s. maxRate must be grater than
41 * 0. If maxRate is zero, it means there is no bandwidth limit.
42 *
43 * @param maxRate
44 * If maxRate is zero, it means there is no bandwidth limit.
45 * @throws IllegalArgumentException
46 */
47 public synchronized void setMaxRate(int maxRate)
48 throws IllegalArgumentException {
49 if (maxRate < 0) {
50 throw new IllegalArgumentException("maxRate can not less than 0");
51 }
52 this.maxRate = maxRate < 0 ? 0 : maxRate;
53 if (maxRate == 0)
54 this.timeCostPerChunk = 0;
55 else
56 this.timeCostPerChunk = (1000000000l * CHUNK_LENGTH)
57 / (this.maxRate * KB);
58 }
59
60 /**
61 * Next 1 byte should do bandwidth limit.
62 */
63 public synchronized void limitNextBytes() {
64 this.limitNextBytes(1);
65 }
66
67 /**
68 * Next len bytes should do bandwidth limit
69 *
70 * @param len
71 */
72 public synchronized void limitNextBytes(int len) {
73 this.bytesWillBeSentOrReceive += len;
74
75 /* We have sent CHUNK_LENGTH bytes */
76 while (this.bytesWillBeSentOrReceive > CHUNK_LENGTH) {
77 long nowTick = System.nanoTime();
78 long missedTime = this.timeCostPerChunk
79 - (nowTick - this.lastPieceSentOrReceiveTick);
80 if (missedTime > 0) {
81 try {
82 Thread.sleep(missedTime / 1000000,
83 (int) (missedTime % 1000000));
84 } catch (InterruptedException e) {
85 e.printStackTrace();
86 }
87 }
88 this.bytesWillBeSentOrReceive -= CHUNK_LENGTH;
89 this.lastPieceSentOrReceiveTick = nowTick
90 + (missedTime > 0 ? missedTime : 0);
91 }
92 }
93 }
94
2
3 import java.io.IOException;
4 import java.io.InputStream;
5
6 /**
7 * @author Le
8 *
9 */
10 public class DownloadLimiter extends InputStream {
11 private InputStream is = null;
12 private BandwidthLimiter bandwidthLimiter = null;
13
14 public DownloadLimiter(InputStream is, BandwidthLimiter bandwidthLimiter)
15 {
16 this.is = is;
17 this.bandwidthLimiter = bandwidthLimiter;
18 }
19 @Override
20 public int read() throws IOException {
21 if(this.bandwidthLimiter != null)
22 this.bandwidthLimiter.limitNextBytes();
23 return this.is.read();
24 }
25
26 public int read(byte b[], int off, int len) throws IOException
27 {
28 if (bandwidthLimiter != null)
29 bandwidthLimiter.limitNextBytes(len);
30 return this.is.read(b, off, len);
31 }
32 }
2
3 import java.io.IOException;
4 import java.io.OutputStream;
5
6 /**
7 * @author Le
8 *
9 */
10 public class UploadLimiter extends OutputStream {
11 private OutputStream os = null;
12 private BandwidthLimiter bandwidthLimiter = null;
13
14 public UploadLimiter(OutputStream os, BandwidthLimiter bandwidthLimiter)
15 {
16 this.os = os;
17 this.bandwidthLimiter = bandwidthLimiter;
18 }
19
20 @Override
21 public void write(int b) throws IOException {
22 if (bandwidthLimiter != null)
23 bandwidthLimiter.limitNextBytes();
24 this.os.write(b);
25 }
26
27 public void write(byte[] b, int off, int len) throws IOException {
28 if (bandwidthLimiter != null)
29 bandwidthLimiter.limitNextBytes(len);
30 this.os.write(b, off, len);
31 }
32
33 }
2 //其它初始化略
2 //```java
3 DownloadLimiter dl = new DownloadLimiter(socket.getInputStream(), new BandwidthLimiter(6250));
4 is = new DataInputStream(dl);
5
6 //读数据
7 int len = is.readInt();
8 ByteBuffer buffer = ByteBuffer.allocate(4 + len);
9 buffer.putInt(len);
10 is.readFully(buffer.array(), 4, buffer.remaining());
11 //```
12
13 //以一定的速率写数据到socket
14 //```java
15 UploadLimiter ul = new UploadLimiter(socket.getOutputStream(), new BandwidthLimiter(6250));
16 ul.write(

17 //```
Java程序如何限速(控制下载和上传速度)的更多相关文章
- 重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性
[源码下载] 重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性 作者:webabcd 介 ...
- 重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传
[源码下载] 重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台任务 后台 ...
- github下载和上传项目
git下载和上传项目 下载: git clone +地址 上传: 1.git init 在当前项目的目录中生成本地的git管理(多一个.git文件夹,为隐藏文件) 2.git add .(注意最后面有 ...
- Java初学者作业——编写JAVA程序,在控制台中输入六位员工的姓名,通过随机点名方式,输出当选组长的员工姓名。
返回本章节 返回作业目录 需求说明: 编写JAVA程序,在控制台中输入六位员工的姓名,通过随机点名方式,输出当选组长的员工姓名. 实现思路: (1)定义字符串类型的数组names,长度为6,用于存储六 ...
- Java初学者作业——编写Java程序,在控制台中输入一个数字,要求定义方法实现找出能够整除该数字的所有数字。
返回本章节 返回作业目录 需求说明: 编写Java程序,在控制台中输入一个数字,要求定义方法实现找出能够整除该数字的所有数字. 实现思路: 定义方法findNums(),用于实现查找所有能够整除指定数 ...
- Java初学者作业——编写 Java 程序,在控制台中输入日期,计算该日期是对应年份的第几天。
返回本章节 返回作业目录 需求说明: 编写 Java 程序,在控制台中输入日期,计算该日期是对应年份的第几天. 实现思路: (1)声明变量 year.month和 date,用于存储日期中的年.月.日 ...
- Ubuntu 16.04通过Trickle限制某个软件的下载/上传速度
在Linux下没有Windows使用360那样去限制某个软件的速度. 但是通过Trickle可以设置某个软件的网速,但是前提是通过Trickle命令连带启动这个软件才可以,不能中途去设置. 比如现在很 ...
- window系统使用tftp下载和上传文件
安装tftp32服务器 首先需要安装tftp服务器:tftpd32 , 下载以后的目录如下: tftp使用帮助 命令提示符(cmd): 直接运行tftpd32.exe tftp命令的用法: 关于tft ...
- selenium和AutoIt工具辅助下载和上传
上传 根据AutoIt Windows Info 所识别到的控件信息打开SciTE Script Editor编辑器,编写脚本. ;ControlFocus("title",&qu ...
随机推荐
- 3 java 笔记
1 垃圾回收机制能够很好地提高编程效率 2 垃圾回机制保护程序的完成性 3 面向对象的三种基本特征:继承,封装,多态 4 面向对象的方式:OOA(面向对象的分析),OOD(面向对象的设计)和OOP(面 ...
- 关于IDEA导入依赖问题,阿里云下载不了
关于阿里云,有部分数据是不能够下载的,就拿ojdbc8-12.2.0.1.0.jar来说 pom.xml <!--Oracle驱动 因为maven仓库下载不了,采用本地导入--> < ...
- axiso基本使用及python接收处理
安装$ npm install axios 1.发送get请求: axios.get("/api/v1.0/cars?id=132").then(function(res){ co ...
- 【转】make menuconfig/.config/Kconfig解析
当执行#make menuconfig时会出现内核的配置界面,所有配置工具都是通过读取"arch/$(ARCH)/Kconfig"文件来生成配置界面,这个文件就是所有配置的总入口, ...
- C++ 批量打开写入文件
用到了C++17的filesystem 库 说明:这个函数主要是用来处理日志中不同Thread的日志,主要目的是将不同Thread的日志写到不同的文件中 int GetThreadTime(const ...
- 1.RPC原理学习
1.什么是RPC:远程过程调用协议 RPC(Remote Procedure Call Protocol)— 远程过程调用协议,是一种通过网络从远程计算机程序上请求服务,而不需要 了解底层网络技术的协 ...
- 简单了解Linux文件目录
/bin :获得最小的系统可操作性所需要的命令 /boot :内核和加载内核所需的文件 /dev :终端.磁盘.调制解调器等的设备项 /etc :关键的启动文件和配置文件 /home :用户的主目录 ...
- dubbo框架-学习-dubbo原理
博客:Dubbo原理和源码解析之服务暴露 博客:dubbo实现原理简单介绍
- 生产者消费者问题--BlockingQueue
# 代码: public class App { public static void main(String[] args) { BlockingQueue<Integer> queue ...
- java中用activiti插件连接mysql数据库,自动建表过程中,在配置mysql架包路径“org.activiti.engine.ActivitiException: couldn't check if tables “
java中用activiti插件连接mysql数据库,出现错误: org.activiti.engine.ActivitiException: couldn't check if tables are ...