Java技术体验:HTTP多线程下载,端口侦听和自启动服务[Java编程]
本文“Java技术体验:HTTP多线程下载,端口侦听和自启动服务[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
一个网友恰好需求这个东西,我就把几个技术整合到了一同.包含三个部份,实现时也是一一做到的
多线程的文件下载,HTTP协议
把这个功效做成一个HTTP的服务,侦听在某个端口上,便利非Java的系统利用
把这个功效封装为一个Windows服务,在机械启动时可以自动启动
我们一一看程序.
1、多线程下载
这个主要利用了HTTP协议里面的一个Range参数,他设置了你读取数据的其实位置和终止位置. 常常利用flashget的用户在查看衔接的具体信息时,应当常常看到这个东西.比方
Range:bytes=100-2000
代表从100个字节的位置开始读取,到2000个字节的位置完毕,应读取1900个字节.
程序首先拿到文件的长度,然后分配几个线程去辨别读取各自的一段,利用了
RandomAccessFile
举行随机位置的读写.
下面是完好的下载的代码.
package net.java2000.tools;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;
/**
* HTTP的多线程下载工具.
*
* @author 赵学庆 www.java2000.net
*/
public class HTTPDownloader extends Thread {
// 要下载的页面
private String page;
// 保存的途径
private String savePath;
// 线程数
private int threadNumber = 2;
// 根源地址
private String referer;
// 最小的块尺寸.假如文件尺寸除以线程数小于这个,则会削减线程数.
private int MIN_BLOCK = 10 * 1024;
public static void main(String[] args) throws Exception {
HTTPDownloader d = new HTTPDownloader("http://www.xxxx.net/xxxx.rar", "d://xxxx.rar", 10);
d.down();
}
public void run() {
try {
down();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 下载操作
*
* @throws Exception
*/
public void down() throws Exception {
URL url = new URL(page); // 成立URL
URLConnection con = url.openConnection(); // 成立衔接
int contentLen = con.getContentLength(); // 得到资源长度
if (contentLen / MIN_BLOCK + 1 < threadNumber) {
threadNumber = contentLen / MIN_BLOCK + 1; // 调整下载线程数
}
if (threadNumber > 10) {
threadNumber = 10;
}
int begin = 0;
int step = contentLen / threadNumber;
int end = 0;
for (int i = 0; i < threadNumber; i++) {
end += step;
if (end > contentLen) {
end = contentLen;
}
new HTTPDownloaderThread(this, i, begin, end).start();
begin = end;
}
}
public HTTPDownloader() {
}
/**
* 下载
*
* @param page 被下载的页面
* @param savePath 保存的途径
*/
public HTTPDownloader(String page, String savePath) {
this(page, savePath, 10);
}
/**
* 下载
*
* @param page 被下载的页面
* @param savePath 保存的途径
* @param threadNumber 线程数
*/
public HTTPDownloader(String page, String savePath, int threadNumber) {
this(page, page, savePath, 10);
}
/**
* 下载
*
* @param page 被下载的页面
* @param savePath 保存的途径
* @param threadNumber 线程数
* @param referer 根源
*/
public HTTPDownloader(String page, String referer, String savePath, int threadNumber) {
this.page = page;
this.savePath = savePath;
this.threadNumber = threadNumber;
this.referer = referer;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public String getSavePath() {
return savePath;
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
public int getThreadNumber() {
return threadNumber;
}
public void setThreadNumber(int threadNumber) {
this.threadNumber = threadNumber;
}
public String getReferer() {
return referer;
}
public void setReferer(String referer) {
this.referer = referer;
}
}
/**
* 下载线程
*
* @author 赵学庆 www.java2000.net
*/
class HTTPDownloaderThread extends Thread {
HTTPDownloader manager;
int startPos;
int endPos;
int id;
int curPos;
int BUFFER_SIZE = 4096;
int readByte = 0;
HTTPDownloaderThread(HTTPDownloader manager, int id, int startPos, int endPos) {
this.id = id;
this.manager = manager;
this.startPos = startPos;
this.endPos = endPos;
}
public void run() {
// System.out.println("线程" + id + "启动");
// 成立一个buff
BufferedInputStream bis = null;
RandomAccessFile fos = null;
// 缓冲区大小
byte[] buf = new byte[BUFFER_SIZE];
URLConnection con = null;
try {
File file = new File(manager.getSavePath());
// 成立RandomAccessFile
fos = new RandomAccessFile(file, "rw");
// 从startPos开始
fos.seek(startPos);
// 成立衔接,这里会为每个线程都成立一个衔接
URL url = new URL(manager.getPage());
con = url.openConnection();
con.setAllowUserInteraction(true);
curPos = startPos;
// 设置获得资源数据的范围,从startPos到endPos
con.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);
// 盗链办理
con.setRequestProperty("referer", manager.getReferer() == null ? manager.getPage() : manager.getReferer());
con.setRequestProperty("userAgent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
// 下面一段向按照文件写入数据,curPos为当前写入的未知,这里会判断能否小于endPos,
// 假如超越endPos就代表该线程已经履行完毕
bis = new BufferedInputStream(con.getInputStream());
while (curPos < endPos) {
int len = bis.read(buf, 0, BUFFER_SIZE);
if (len == -1) {
break;
}
fos.write(buf, 0, len);
curPos = curPos + len;
if (curPos > endPos) {
// 获得精确读取的字节数
readByte += len - (curPos - endPos) + 1;
} else {
readByte += len;
}
}
// System.out.println("线程" + id + "已经下载完毕:" + readByte);
bis.close();
fos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
以上是“Java技术体验:HTTP多线程下载,端口侦听和自启动服务[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |