使用java从套接字流中读取多个流?

时间:2012-05-08 13:14:33

标签: java multithreading sockets stream

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

所以底线是我想从一个网站的打开套接字多线程数据读取过程。该过程必须像Internet Download Manager。 如果可能的话,请给我一些教程链接..

4 个答案:

答案 0 :(得分:3)

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

HTTPD协议确实支持Range: header,虽然我不确定有多少Web服务器支持这种行为 - 例如Apache。如果支持,服务器应使用以下标头进行响应:

Accept-Ranges: bytes

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

Range: bytes=21010-47021

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

我认为你问的是http标题

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

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

另见How to assemble the file using the range header?

编辑:示例

这似乎有效

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变量。如果是假的。服务器不支持部分范围,并且会为您提供文件的开头。

答案 3 :(得分:0)

您无法通过套接字随机阅读。原则上,您有两种选择:

  1. 读取整个数据流并将其作为缓冲区(例如字节数组)。将缓冲区暴露给每个线程。

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