本文介绍了如何使用Java编写下载软件并实现多现程下载
网络蚂蚁Falshget 等许多多线程下载软件都是网友的必备工具利用这些工具可以快速从服务器上下载比较大的文件这些工具的工作特性是把服务器端的文件分成几个段每个段分别同时进行下载编写这类程序第一必须对HTTP协议有较为充分的了解第二有效使用多线程编程手段在软件上实现
HTTP 协议的简介
HTTP协议是一种超文本传输协议(Hypertext Transfer Protocol)工作于网络应用层自年起广泛应用于WWW 的全球信息服务HTTP协议的详细说明可以在网上查阅RFCRFC等文档
HTTP 协议老的标准是HTTP/目前最通用的标准是HTTP/HTTP/是在HTTP/基础上的升级增加了一些功能全面兼容HTTP/HTTP/不支持文件断点续传如果服务器使用HTTP/网络蚂蚁的任何多线程下载程序都只能按单线程下载好在目前的Web服务器绝大多数都采用了HTTP/所以下面将基于HTTP/进行介绍
HTTP协议的相关重要命令
基于HTTP的浏览器浏览网页下载文件时工作原理类似客户机/服务器模式浏览器向Web服务器发出一个HTTP请求行Web服务器在收到有效的请求后返回一个状态行或多个响应标题一个空白行和相关文档根据这一工作原理下载程序必须实现向服务器发送请求和获取服务器响应状态的功能
向服务器发送 GET请求命令
一个HTTP请求由一个请求行可选数目的请求标题一个空白行以及在POST情况下的一些额外的数据组成请求行的格式是
请求方法URI HTTP/版本号
GET 命令是浏览器常用的文档请求方法在程序中间使用
GETURI HTTP/
向Web服务器发送请求行(行号)Java 代码如下
……
clientSocket = new Socket(host port)//打开要下载文件服务器的Socket
outStream = new PrintStream(clientSocketgetOutputStream())
……
outStreamprintln(GET+uri+ HTTP/)
outStreamprintln(Host+host)
outStreamprintln(Accept*/* )
outStreamprintln(Referer)
outStreamprintln()
……
注第行给出URL中的主机名和端口号第行说明客户端接收所有MIME类型第行方送一个空白行表明请求行结束
获取服务器响应状态
在发送HTTP请求行以后程序就可以读取服务器的响应状态了HTTP响应状态行包括HTTP 状态码和一些HTTP响应标题
) HTTP状态码
HTTP状态码格式是 HTTP/版本信息的数字表示状态码例子如下
HTTP/ OK // 表示服务器支持HTTP/ 协议成功
HTTP/ OK // 表示服务器支持HTTP/ 协议成功
HTTP/ Not Found // 表示服务器支持HTTP/ 协议访问文件没有找到
在程序中间如果读到HTTP/ OK这样的字符串表明欲下载文件存在该服务器支持断点续传可以使用多线程下载如果读到HTTP/ OK这样的字符串表明欲下载文件存在但该服务器不支持断点续传只可以使用单线程下载
……
while ((line=inStreamreadLine()) != null)//将服务器响应状态读到line
……
if(linesubstring()equals(HTTP/) )//判断是否支持HTTP/
{ if(linecharAt()==)
{
Systemoutprintln(server use )
threadcount=
}
if(!(linesubstring())equals()) //判断请求是否成功
{ Systemoutprintln(ERROR+line)
return false
}
}
) 读取重要的响应标题获得要下载文档的文件长度
如果HTTP状态码表明访问成功服务器会回送一些标题行我们最关注的是ContentLength这一行比如如果服务器回送ContentLength表明请求文件的长度是1000字节所以读取这一行信息可以得到文件的长度信息
……
if(linesubstring()equals(ContentLength) )
{ filelength=LongparseLong(linesubstring()trim())
Systemoutprintln(file length +filelength)
}
……
向服务器发送断点续传请求
如上所述如果服务器支持HTTP/再次向服务器发送GET请求
……
outStreamprintln(GET +uri+HTTP/ )
outStreamprintln(Host+host)
outStreamprintln(Accept*/* )
outStreamprintln(RANGEbytes=+(fileblocklength)*thisthreadid+)
outStreamprintln()
……
第行是关键RANGEbytes=是HTTP/新增内容HTTP/每次传送文件都是从文件头开始即0字节处开始RANGEbytes=XXXX表示要求服务器从文件XXXX字节处开始传送这就是我们平时所说的断点续传!
分割文件多线程下载
使用多线程编程技术同时启动多个线程根据线程个数计算文件分割位置向服务器发送几个不同的下载断点同时接受数据并写入文件就可以实现多线程下载了
……
raf=new RandomAccessFile(filerw)//以随机存取方式打开文件
……
synchronized(raf) //按同步方式把各个线程得到数据分别写入文件
{ rafseek(thisthreadid*(filelength/threadcount)+k*buflength)
rafwrite(readbytes)
……
}
……