如何以编程方式限制下载速度? [英] How to programmatically limit the download speed?

查看:532
本文介绍了如何以编程方式限制下载速度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用以下代码来限制java中文件的下载速度:

I use the following code to limit the download speed of a file in java:

package org;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

class MainClass {

    public static void main(String[] args) {
        download("https://speed.hetzner.de/100MB.bin");
    }

    public static void download(String link) {
        try {
            URL url = new URL(link);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setConnectTimeout(5000);
            con.setReadTimeout(5000);
            InputStream is = con.getInputStream();
            CustomInputStream inputStream = new CustomInputStream(is);
            byte[] buffer = new byte[2024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                System.out.println("downloaded : " + len);
                //save file
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static class CustomInputStream extends InputStream {

        private static final int MAX_SPEED = 8 * 1024;
        private final long ONE_SECOND = 1000;
        private long downloadedWhithinOneSecond = 0L;
        private long lastTime = System.currentTimeMillis();

        private InputStream inputStream;

        public CustomInputStream(InputStream inputStream) {
            this.inputStream = inputStream;
            lastTime = System.currentTimeMillis();
        }

        @Override
        public int read() throws IOException {
            long currentTime;
            if (downloadedWhithinOneSecond >= MAX_SPEED
                    && (((currentTime = System.currentTimeMillis()) - lastTime) < ONE_SECOND)) {
                try {
                    Thread.sleep(ONE_SECOND - (currentTime - lastTime));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                downloadedWhithinOneSecond = 0;
                lastTime = System.currentTimeMillis();
            }
            int res = inputStream.read();
            if (res >= 0) {
                downloadedWhithinOneSecond++;
            }
            return res;
        }

        @Override
        public int available() throws IOException {
            return inputStream.available();
        }

        @Override
        public void close() throws IOException {
            inputStream.close();
        }
    }

}

下载速度成功受限,但出现了新问题。当下载正在进行中,并且我与互联网断开连接时,下载不会结束并持续一段时间。当我断开互联网连接时,抛出 java.net.SocketTimeoutException 异常需要10秒以上。我真的不明白后台会发生什么。为什么会出现这个问题?我该怎么做才能解决这个问题?非常感谢你。

The download speed is successfully limited, but a new problem arises. When the download is in progress, and I disconnect from the internet, the download does not end and continues for a while. When i disconnect the internet connection, it takes more than 10 seconds to throw a java.net.SocketTimeoutException exception. I do not really understand what happens in the background. why does this problem arise? What can i do to solve this problem? Thank you so much.

如果我的句子语法不正确,我会提前道歉。因为我不会说英语。

I apologize in advance if the grammar of my sentences is not correct. Because I can't speak English well.

推荐答案

你的费率限制实际上并不像你认为的那样有效,因为数据实际上并不是每字节发送一次,而是以数据包形式发送。这些数据包是缓冲的,你观察到的(没有连接下载继续)只是你的流读取缓冲区。一旦它到达缓冲区的末尾,它会在抛出超时之前等待5秒(因为这是你配置的)。

Your rate limit doesn't actually work like you think it does, because the data is not actually sent byte-per-byte, but in packets. These packets are buffered, and what you observe (download continues without connection) is just your stream reading the buffer. Once it reaches the end of your buffer, it waits 5 seconds before the timeout is thrown (because that is what you configured).

你将速率设置为8 kB / s,正常的数据包大小通常约为1 kB,最高可达64 kB,因此您仍然需要8秒才能读取相同的数据包。此外,可能已经发送和缓冲了多个数据包。还有一个接收缓冲区,这个缓冲区可以小到8 - 32 kB到几MB 。所以你真的只是从缓冲区读书。

You set the rate to 8 kB/s, and the normal packet size is normally around 1 kB and can go up to 64 kB, so there would be 8 seconds where you are still reading the same packet. Additionally it is possible that multiple packets were already sent and buffered. There exists also a receive buffer, this buffer can be as small as 8 - 32 kB up to several MB. So really you are just reading from the buffer.

只是为了澄清,你正在做正确的事。平均而言,费率将限制为您指定的费率。服务器将发送一堆数据,然后等到客户端已经清空其缓冲区足以接收更多数据。

Just to clarify, you are doing the right thing. On average, the rate will be limited to what you specify. The server will send a bunch of data, then wait until the client has emptied its buffer enough to receive more data.

这篇关于如何以编程方式限制下载速度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆