【问题标题】:How to close apache's httpclient after Range requestRange请求后如何关闭apache的httpclient
【发布时间】:2016-08-21 14:34:39
【问题描述】:

我正在构建一个下载应用程序,以使用 Range 请求和 apache 的 httpclient 通过 HTTP 从我的服务器下载电影。我在执行请求和处理响应时没有问题,但是如果我尝试关闭与服务器的连接(关闭应用程序时)以稍后恢复下载,则连接保持打开并继续下载。

整个下载是在一个线程中构建的,可以同时处理多个下载。 我有一个private boolean running 来阻止线程永远执行。

这就是我执行请求和处理响应数据的方式:

HttpGet req = new HttpGet(url.toString());

req.setHeader("If-Range", "Wed, 11 Jan 1984 08:00:00 GMT");
req.setHeader("Range", "bytes=" + (bytes_read+1) + "-");

HttpResponse res = client.execute(req);

if (res.getStatusLine().getStatusCode() == 206) {
    ReadableByteChannel rbc = Channels.newChannel(res.getEntity().getContent());
    FileChannel fc = new FileOutputStream(new File("test.mp4", false).getChannel();
    int n;
    ByteBuffer buffer = ByteBuffer.allocate(16*8192);
    while((n = rbc.read(buffer)) > 0 && running){ 
        buffer.flip();
        fc.write(buffer);
        buffer.clear();
    }
}

只要我不尝试中断下载,我的这部分代码就可以正常工作。

但是当我尝试像这样关闭下载时,

public void shutdown(){
    running = false;
    rbc.close();
    fc.close();
    client.close();
}

关闭方法的执行在rbc.close(); 处阻塞。我调试了这部分代码。 running 标志完成了它的工作并导致线程结束。 但是查看控制台,您可以看到在调用 ReadableByteChannel 的close() 方法后,它开始从连接中下载内容,但什么也没做。它不是关闭连接而是下载到最后。

现在我的问题是:如何在频道关闭之前停止频道以从服务器下载全部内容。

关闭 httpclient 会引发多个异常。

【问题讨论】:

    标签: java multithreading apache http nio


    【解决方案1】:

    我认为问题在于您指定的范围请求标头。它要求服务器从指定的字节数开始发送所有字节。稍后在您的代码中使用 res.getEntity().getContent() 可能会读取服务器发送的所有数据。我建议只请求某些数据块,例如

    req.setHeader("Range", "bytes=" + (bytes_read+1) + "-" + (bytes_read+1 + CHUNCK_SIZE));
    

    您可以根据自己的喜好定义 CHUNK_SIZE。然后您可以重复调用此方法以读取更多字节(如果有)。

    【讨论】:

    • 您会为 CHUNK_SIZE 推荐哪种尺寸?介于 10 或 20MB 之间?我不想等待程序在慢速连接时关闭
    • 这取决于您的连接速度以及您愿意等待多长时间。 10 或 20 MB 对我来说似乎是合理的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2012-05-05
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    相关资源
    最近更新 更多