服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

java网络蚂蚁的制作流程


  java网络蚂蚁的制作流程


“网络蚂蚁”、falshget 等许多多线程下载软件都是网友的必备工具,利用这些工具可以快速从服务器上下载比较大的文件,这些工具的工作特性是把服务器端的文件分成几个段,每个段分别、同时进行下载。编写这类程序,第一、必须对http协议有较为充分的了解;第二、有效使用多线程编程手段在软件上实现。

http 协议的简介

http协议是一种超文本传输协议(hypertext transfer protocol),工作于网络应用层,自1990年起广泛应用于www 的全球信息服务,http协议的详细说明可以在网上查阅rfc2518、rfc2616等文档。

http状态码

http状态码格式是 http/版本信息的数字表示。状态码例子如下:

http/1.0 200 ok // 表示服务器支持http/1.0 协议,成功

http/1.1 200 ok // 表示服务器支持http/1.1 协议,成功

http/1.0 404 not found // 表示服务器支持http/1.0 协议,访问文件没有找到

在程序中间,如果读到“http/1.1 200 ok”这样的字符串,表明欲下载文件存在、该服务器支持断点续传,可以使用多线程下载。如果读到“http/1.0 200 ok”这样的字符串,表明欲下载文件存在、但该服务器不支持断点续传,只可以使用单线程下载。


读取重要的响应标题,获得要下载文档的文件长度

如果http状态码表明访问成功,服务器会回送一些标题行,我们最关注的是content-length 这一行,比如,如果服务器回送“content-length:1000”,表明请求文件的长度是1000字节,所以读取这一行信息,可以得到文件的长度信息:

例如:get /down.zip http/1.1
accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
excel, application/msword, application/vnd.ms-powerpoint, */*
accept-language: zh-cn
accept-encoding: gzip, deflate
user-agent: mozilla/4.0 (compatible; msie 5.01; windows nt 5.0)
connection: keep-alive

200
content-length=106786028
accept-ranges=bytes
date=mon, 30 apr 2001 12:56:11 gmt
etag=w/"02ca57e173c11:95b"
content-type=application/octet-stream
server=microsoft-iis/5.0
last-modified=mon, 30 apr 2001 12:56:11 gmt
所谓断点续传,也就是要从文件已经下载的地方开始继续下载。所以在客户端浏览器传给
web服务器的时候要多加一条信息--从哪里开始。
下面是用自己编的一个"浏览器"来传递请求信息给web服务器,要求从2000070字节开始。
get /down.zip http/1.0
user-agent: netfox
range: bytes=2000070-
accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2


仔细看一下就会发现多了一行range: bytes=2000070-
这一行的意思就是告诉服务器down.zip这个文件从2000070字节开始传,前面的字节不用传了。
服务器收到这个请求以后,返回的信息如下:
206
content-length=106786028
content-range=bytes 2000070-106786027/106786028
date=mon, 30 apr 2001 12:55:20 gmt
etag=w/"02ca57e173c11:95b"
content-type=application/octet-stream
server=microsoft-iis/5.0
last-modified=mon, 30 apr 2001 12:55:20 gmt


和前面服务器返回的信息比较一下,就会发现增加了一行:
content-range=bytes 2000070-106786027/106786028
返回的代码也改为206了,而不再是200了。


知道了以上原理,就可以进行断点续传的编程了。



分割文件,多线程下载

使用多线程编程技术,同时启动多个线程,根据线程个数,计算文件分割位置,向服务器发送几个不同的下载断点,同时接受数据并写入文件,就可以实现多线程下载了。




java实现断点续传的关键几点


(1)用什么方法实现提交range: bytes=2000070-。
当然用最原始的socket是肯定能完成的,不过那样太费事了,其实java的net包中提供了这种功能。代码如下:

url url = new url("http://www.sjtu.edu.cn/down.zip");
httpurlconnection httpconnection = (httpurlconnection)url.openconnection();


//设置user-agent
httpconnection.setrequestproperty("user-agent","netfox");
//设置断点续传的开始位置
httpconnection.setrequestproperty("range","bytes=2000070");
//获得输入流
inputstream input = httpconnection.getinputstream();



从输入流中取出的字节流就是down.zip文件从2000070开始的字节流。
大家看,其实断点续传用java实现起来还是很简单的吧。
接下来要做的事就是怎么保存获得的流到文件中去了。


保存文件采用的方法。
我采用的是io包中的randaccessfile类。
操作相当简单,假设从2000070处开始保存文件,代码如下:
randomaccess osavedfile = new randomaccessfile("down.zip","rw");
long npos = 2000070;
//定位文件指针到npos位置
osavedfile.seek(npos);
byte[] b = new byte[1024];
int nread;
//从输入流中读入字节流,然后写到文件中
while((nread=input.read(b,0,1024)) > 0)
{
osavedfile.write(b,0,nread);
}

怎么样,也很简单吧。
接下来要做的就是整合成一个完整的程序了。包括一系列的线程控制等等。



部分程序原码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.tree.*;
import javax.swing.border.*;
import java.net.*;
import java.util.*;
import java.io.*;

public class testants extends jframe{
private jmenu file,edit,download,view,option,tool,help;
private jmenuitem exit,add,preference,bookmark,helptopic,about;
private static jmenuitem start,stop;
private jcheckboxmenuitem istoolbar,isstatusbar;
private jmenubar menubar;
private jtoolbar toolbar;
private jbutton addbut,preferencebut,helpbut,exitbut;
private static jbutton startbut,stopbut;
private jsplitpane leftsp;
private jcomponent left,right;
private jlabel statusbar,label,lurl,lpath,lname,lnum;
public static jtextfield turl,tpath,tname,tnum;
private jpanel panel;
private defaulttreecellrenderer render;
private jscrollpane scrollpane;
private jtree tree;
public static jprogressbar pb;
private listener listener;
private container contentpane;

public testants(string name){
super(name);
init();
}

public void init(){
listener = new listener();
//toolbar component add
startbut = new jbutton("start");
startbut.setenabled(false);
startbut.settooltiptext("start");
startbut.addactionlistener(listener);
stopbut = new jbutton("stop");
stopbut.setenabled(false);
stopbut.settooltiptext("stop");
stopbut.addactionlistener(listener);
addbut = new jbutton("add...");
addbut.settooltiptext("add...");
addbut.addactionlistener(listener);
preferencebut = new jbutton("preference...");
preferencebut.settooltiptext("preference...");
preferencebut.addactionlistener(listener);
helpbut = new jbutton("help");
helpbut.settooltiptext("help");
helpbut.addactionlistener(listener);
exitbut = new jbutton("exit");
exitbut.settooltiptext("exit");
exitbut.addactionlistener(listener);

toolbar = new jtoolbar();
toolbar.add(startbut);
toolbar.add(stopbut);
toolbar.add(addbut);
toolbar.add(preferencebut);
toolbar.addseparator();
toolbar.add(helpbut);
toolbar.addseparator();
toolbar.add(exitbut);

//leftsp component
leftsp = new jsplitpane();
leftsp.setcontinuouslayout(false);
leftsp.setdividersize(10);
leftsp.setdividerlocation(204);
left = (jcomponent)leftsp.getleftcomponent();
right = (jcomponent)leftsp.getrightcomponent();
left.setbackground(color.green);
right.setbackground(color.green);

pb = new jprogressbar(0,100);
pb.setforeground(color.red);
label = new jlabel("progressmonitor..");
lurl = new jlabel("download url:");
lpath = new jlabel("save to:");
lname = new jlabel("rename as:");
lnum = new jlabel("progress num:");
turl = new jtextfield(20);
turl.setenabled(false);
tpath = new jtextfield(20);
tpath.setenabled(false);
tname = new jtextfield(20);
tname.setenabled(false);
tnum = new jtextfield(20);
tnum.setenabled(false);
label.setforeground(color.blue);
panel = new jpanel();
panel.setbackground(color.green);
panel.add(label);
panel.add(pb);
panel.add(lurl);
panel.add(turl);
panel.add(lpath);
panel.add(tpath);
panel.add(lname);
panel.add(tname);
panel.add(lnum);
panel.add(tnum);
right.add(panel,borderlayout.north);

render = new defaulttreecellrenderer();
render.setbackgroundnonselectioncolor(color.green);
render.settextnonselectioncolor(color.blue);
render.settextselectioncolor(color.red);
tree = new jtree(createnodes());
tree.setcellrenderer(render);
tree.setbackground(color.green);
scrollpane = new jscrollpane(tree);
left.add(scrollpane);


//statusbar
statusbar = new jlabel("statusbar");

//menubar
file = new jmenu("file");
file.setmnemonic('f');
exit = new jmenuitem("exit");
exit.setmnemonic('x');
exit.addactionlistener(listener);
file.add(exit);

edit = new jmenu("edit");
edit.setmnemonic('e');
add = new jmenuitem("add...");
add.setmnemonic('a');
add.addactionlistener(listener);
edit.add(add);

download = new jmenu("download");
download.setmnemonic('d');
start = new jmenuitem("start");
start.setenabled(false);
start.addactionlistener(listener);
stop = new jmenuitem("stop");
stop.setenabled(false);
stop.addactionlistener(listener);
download.add(start);
download.add(stop);

view = new jmenu("view");
view.setmnemonic('v');
istoolbar = new jcheckboxmenuitem("toolbar");
isstatusbar = new jcheckboxmenuitem("statusbar");
view.add(istoolbar);
view.add(isstatusbar);

option = new jmenu("option");
option.setmnemonic('o');
preference = new jmenuitem("preference..");
preference.addactionlistener(listener);
option.add(preference);

tool = new jmenu("tool");
tool.setmnemonic('t');
bookmark = new jmenuitem("bookmark..");
bookmark.addactionlistener(listener);
tool.add(bookmark);

help = new jmenu("help");
help.setmnemonic('h');
helptopic = new jmenuitem("help topic...");
helptopic.addactionlistener(listener);
about = new jmenuitem("about...");
about.addactionlistener(listener);
help.add(helptopic);
help.add(about);

menubar = new jmenubar();
menubar.add(file);
menubar.add(edit);
menubar.add(download);
menubar.add(view);
menubar.add(option);
menubar.add(tool);
menubar.add(help);

//add all
contentpane = getcontentpane();
contentpane.add(toolbar,borderlayout.north);
contentpane.add(leftsp,borderlayout.center);
contentpane.add(statusbar,borderlayout.south);
setjmenubar(menubar);
}

public defaultmutabletreenode createnodes(){
defaultmutabletreenode rootnode = new defaultmutabletreenode("virtual folder");
defaultmutabletreenode missionstate=new defaultmutabletreenode("mission state");
defaultmutabletreenode downdate=new defaultmutabletreenode("down date");
defaultmutabletreenode today=new defaultmutabletreenode("today");
defaultmutabletreenode yesterday=new defaultmutabletreenode("yesterday");
defaultmutabletreenode lastweek=new defaultmutabletreenode("last week");
defaultmutabletreenode lastweek3=new defaultmutabletreenode("last week3");
defaultmutabletreenode normal=new defaultmutabletreenode("normal");
defaultmutabletreenode running=new defaultmutabletreenode("running");
rootnode.add(missionstate);
rootnode.add(downdate);
downdate.add(today);
downdate.add(yesterday);
downdate.add(lastweek);
missionstate.add(normal);
missionstate.add(running);
return rootnode;
}

public static void main(string[] args) {
testants ta = new testants("网络蚂蚁ant");
ta.setsize(600,410);
ta.setdefaultcloseoperation(jframe.exit_on_close);
ta.show();
}

public static void setstarttrue(){
startbut.setenabled(true);
start.setenabled(true);
}

public static void setstartfalse(){
startbut.setenabled(false);
start.setenabled(false);
}

public static void setstoptrue(){
startbut.setenabled(true);
start.setenabled(true);
}

public static void setstopfalse(){
startbut.setenabled(false);
start.setenabled(false);
}

public void showadddialog(){
adddialog ad =new adddialog(this);
ad.setsize(380,340);
ad.setmodal(true);
ad.center();
ad.setdefaultcloseoperation(windowconstants.dispose_on_close);
ad.show();
}

class listener implements actionlistener{
public void actionperformed(actionevent e){
string arg=e.getactioncommand();
if(arg=="exit"){
system.exit(0);
}else if(arg=="add..."){
showadddialog();//
}else if(arg=="start"){
splitfile sf = new splitfile();
sf.start();
}
}
}
}

如果想获得java版ant的原码:http://www.fls-cts.com/kkjvk/

扫描关注微信公众号