有没有办法从打开的套接字流中随机读取字节?假设我在网站上打开了一个数据流。传统的java类使我能够顺序访问数据。像一个链表。我想随机读取数据,如从数组的随机位置读取数据。假设数据大小是2048 KB,我希望用1个线程读取0到1204 KB,同时想要使用另一个线程从1205到2048 KB读取数据。
所以底线是我想从一个网站的打开套接字多线程数据读取过程。该过程必须像Internet Download Manager。 如果可能的话,请给我一些教程链接..
答案 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)
您无法通过套接字随机阅读。原则上,您有两种选择:
读取整个数据流并将其作为缓冲区(例如字节数组)。将缓冲区暴露给每个线程。
独立读取每个线程中的整个数据流,让每个线程忽略所有不应读取的内容。