0

有没有办法从打开的套接字流中随机读取字节?假设我在网站中打开了一个数据流。传统的 java 类让我可以顺序访问数据。像一个链表。我想随机读取数据,例如从数组的随机位置读取数据。假设如果数据大小为 2048 KB,我想用 1 个线程从 0 读取到 1204 KB,同时想使用另一个线程从 1205 到 2048 KB 读取数据。

所以底线是我想从网站打开的套接字中对数据读取过程进行多线程处理。该过程必须类似于 Internet 下载管理器。如果可能的话,请给我一些教程链接..

4

4 回答 4

3

无法使用多个线程从网站流中的随机位置读取。数据以线性流的形式下降,并且没有标准方法可以在多个线程中转到流中的不同位置。但是,多个线程可以同时下载不同的文件。

HTTPD 协议确实支持Range:标头,尽管我不确定有多少 Web 服务器支持该行为——例如 Apache。如果支持,服务器应使用以下标头进行响应:

Accept-Ranges: bytes

然后客户端可以请求文件的特定偏移量/长度:

Range: bytes=21010-47021

有了这个,您可以同时从不同范围下载多个线程,但我不确定这将如何加快下载速度,除非您从多个服务器请求。您很可能会遇到磁盘和网络限制。

于 2012-05-08T13:16:38.820 回答
1

来自套接字的数据按顺序到达。您必须使用一些相当大的缓冲来避免这种情况。

于 2012-05-08T13:16:53.583 回答
1

我认为您要问的是http标头

Accept-Ranges: bytes
Range: bytes=0-8999

这将指示服务器只发送一些文件。然后,您将按顺序读取流。

另请参阅如何使用范围标头组装文件?

编辑:示例

这似乎有效

public static void main(String[] args) throws MalformedURLException, IOException {
    URLConnection conn = new URL("http://ftp.debian.org/debian/dists/stable/Contents-i386.gz")
            .openConnection();
    conn.addRequestProperty("Accept-Ranges","bytes");
    conn.addRequestProperty("Range", "bytes=8000000-16000000");
    InputStream input = conn.getInputStream();
    List<String> serverranges = conn.getHeaderFields().get("Accept-Ranges");
    boolean ispartial = serverranges != null && serverranges.get(0).equals("bytes");
    byte[] b = new byte[1024];
    int l ;
    System.out.println(ispartial);
    while((l=input.read(b, 0, b.length))>0){
        // if isPartial=true, we have server support. We received partial file.
        //do stuff with b,l
    }
}

请务必注意,并非所有服务器都支持此功能,因此请检查 isPartial 变量。如果是假的。服务器不支持部分范围,并将为您提供文件的开头。

于 2012-05-08T13:24:01.607 回答
0

您不能通过套接字随机读取。原则上,您有两种选择:

  1. 读取整个数据流并将其放入缓冲区(例如字节数组)。将缓冲区公开给每个线程。

  2. 独立读取每个线程中的整个数据流,让每个线程忽略不应该读取的所有内容。

于 2012-05-08T13:22:04.697 回答