java socket第三方库_Java基于Socket实现HTTP下载客户端
没有借助任何第三方库,完全基于JAVA Socket实现一个最小化的HTTP文件下载客户端。完整的演示如何通过Socket实现下载文件的HTTP请求(request header)发送如何从Socket中接受HTTP响应(Response header, Response body)报文并解析与保存文件内容。如何通过SwingWork实现UI刷新,实时显示下载进度。
首先看一下UI部分:
【添加下载】按钮:
点击弹出URL输入框,用户Copy要下载文件URL到输入框以后,点击[OK]按钮即开始
下载
【清除完成】按钮:
清除所有已经下载完成的文件列表
文件下载状态分为以下几种:
package com.gloomyfish.socket.tutorial.http.download;
public enum DownLoadStatus {
NOT_STARTED,
IN_PROCESS,
COMPLETED,
ERROR
}
UI部分主要是利用Swing组件完成。点击【添加下载】执行的代码如下:
final JDialog dialog = new JDialog(this,"Add File Link",true);
dialog.getContentPane().setLayout(new BorderLayout());
// dialog.setSize(new Dimension(400,200));
final URLFilePanel panel = new URLFilePanel();
panel.setUpListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
if("OK".equals(e.getActionCommand())){
if(panel.validateInput()) {
DownloadDetailStatusInfoModel data = new DownloadDetailStatusInfoModel(panel.getValidFileURL());
tableModel.getData().add(data);
startDownlaod();
refreshUI();
}
dialog.setVisible(false);
dialog.dispose();
} else if("Cancel".equals(e.getActionCommand())) {
dialog.setVisible(false);
dialog.dispose();
}
}});
dialog.getContentPane().add(panel, BorderLayout.CENTER);
dialog.pack();
centre(dialog);
dialog.setVisible(true);
【清除完成】按钮执行的代码如下:
private void clearDownloaded() {
List downloadedList = new ArrayList();
for(DownloadDetailStatusInfoModel fileStatus : tableModel.getData()) {
if(fileStatus.getStatus().toString().equals(DownLoadStatus.COMPLETED.toString())) {
downloadedList.add(fileStatus);
}
}
tableModel.getData().removeAll(downloadedList);
refreshUI();
}
让JFrame组件居中显示的代码如下:
public static void centre(Window w) {
Dimension us = w.getSize();
Dimension them = Toolkit.getDefaultToolkit().getScreenSize();
int newX = (them.width - us.width) / 2;
int newY = (them.height - us.height) / 2;
w.setLocation(newX, newY);
}
HTTP协议实现部分:
概述:HTTP请求头与相应头报文基本结构与解释
HTTP请求:一个标准的HTTP请求报文如
其中请求头可以有多个,message-body可以没有,不是必须的。请求行的格式如下:
Request-Line = Method SP Request-URI SPHTTP-Version CRLF 举例说明如下:
Request-Line = GET http://www.w3.org/pub/WWW/TheProject.htmlHTTP/1.1\r\n
其中SP表示空格, CRLF表示回车换行符\r\n
当你想要上传文件时候,使用Post方式来填写数据到message-body中即可。发送一个
简单的HTTP请求报文如下:
GET /pub/WWW/TheProject.html HTTP/1.1\r\n
\r\n
HTTP响应:一个标准的HTTP响应报文如下
最先得到是状态行,其格式如下:
Status-Line = HTTP-Version SP Status-CodeSP Reason-Phrase CRLF, 一个状态行的简单例子如下:Status-Line = HTTP/1.1 200 OK一般大家最喜欢的就是Status-Code会给你很多提示,最常见的就是404,500等状态码。状态码的意思可以参考RFC2616中的解释。下载文件最要紧是的检查HTTP响应头中的Content-Length与Content-Type两
个中分别声明了文件的长度与文件的类型。其它如Accept-Ranges表示接受多少到多少的字节。可能在多线程下载中使用。搞清楚了HTTP请求与响应的报文格式以后,我们就可以通过Socket按照报文格式解析内容,发送与读取HTTP请求与响应。具体步骤
如下:
一、根据用户输入的文件URL建立Socket连接
URL url = new URL(fileInfo.getFileURL());
String host = url.getHost();
int port = (url.getPort() == -1) ? url.getDefaultPort():url.getPort();
System.out.println("Host Name = " + host);
System.out.println("port = " + port);
System.out.println("File URI = " + url.getFile());
// create socket and start to construct the request line
Socket socket = new Socket();
SocketAddress address = new InetSocketAddress(host, port);
socket.connect(address);
用了URL类来把用户输入的url string变成容易解析一点的URL。
二、构造HTTP请求
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF8"));
String requestStr = "GET " + url.getFile() + " HTTP/1.1\r\n"; // request line
// construct the request header - 构造HTTP请求头(request header)
String hostHeader = "Host: " + host + "\r\n";
String acceptHeader = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
String charsetHeader = "Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3\r\n";
String languageHeader = "Accept-Language: zh-CN,zh;q=0.8\r\n";
String keepHeader = "Connection: close\r\n";
三、发送HTTP请求
// 发送HTTP请求
bufferedWriter.write(requestStr);
bufferedWriter.write(hostHeader);
bufferedWriter.write(acceptHeader);
bufferedWriter.write(charsetHeader);
bufferedWriter.write(languageHeader);
bufferedWriter.write(keepHeader);
bufferedWriter.write("\r\n"); // 请求头信息发送结束标志
bufferedWriter.flush();
四、接受HTTP响应并解析内容,写入创建好的文件
// 准备接受HTTP响应头并解析
CustomDataInputStream input = new CustomDataInputStream(socket.getInputStream());
File myFile = new File(fileInfo.getStoreLocation() + File.separator + fileInfo.getFileName());
String content = null;
HttpResponseHeaderParser responseHeader = new HttpResponseHeaderParser();
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(myFile));
boolean hasData = false;
while((content = input.readHttpResponseHeaderLine()) != null) {
System.out.println("response header contect -->> " + content);
responseHeader.addResponseHeaderLine(content);
if(content.length() == 0) {
hasData = true;
}
if(hasData) {
int totalBytes = responseHeader.getFileLength();
if(totalBytes == 0) break; // no response body and data
int offset = 0;
byte[] myData = null;
if(totalBytes >= 2048) {
myData = new byte[2048];
} else {
myData = new byte[totalBytes];
}
int numOfBytes = 0;
while((numOfBytes = input.read(myData, 0, myData.length)) > 0 && offset < totalBytes) {
offset += numOfBytes;
float p = ((float)offset) / ((float)totalBytes) * 100.0f;
if(offset > totalBytes) {
numOfBytes = numOfBytes + totalBytes - offset;
p = 100.0f;
}
output.write(myData, 0, numOfBytes);
updateStatus(p);
}
hasData = false;
break;
}
}
简单的HTTP响应头解析类HttpResponseHeaderParser代码如下:
package com.gloomyfish.socket.tutorial.http.download;
import java.util.HashMap;
import java.util.Map;
/**
* it can parse entity header, response head
* and response line
* refer to RFC2616,关于HTTP响应头,请看RFC文档,描写的很详细啊!!
*/
public class HttpResponseHeaderParser {
public final static String CONTENT_LENGTH = "Content-Length";
public final static String CONTENT_TYPE = "Content-Type";
public final static String ACCEPT_RANGES = "Accetp-Ranges";
private Map headerMap;
public HttpResponseHeaderParser() {
headerMap = new HashMap();
}
/**
*
get the response header key value pair
* @param responseHeaderLine
*/
public void addResponseHeaderLine(String responseHeaderLine) {
if(responseHeaderLine.contains(":")) {
String[] keyValue = responseHeaderLine.split(": ");
if(keyValue[0].equalsIgnoreCase(CONTENT_LENGTH)) {
headerMap.put(CONTENT_LENGTH, keyValue[1]);
} else if(keyValue[0].equalsIgnoreCase(CONTENT_TYPE)) {
headerMap.put(CONTENT_TYPE, keyValue[1]);
} else {
headerMap.put(keyValue[0], keyValue[1]);
}
}
}
public int getFileLength() {
if(headerMap.get(CONTENT_LENGTH) == null){
return 0;
}
return Integer.parseInt(headerMap.get(CONTENT_LENGTH));
}
public String getFileType() {
return headerMap.get(CONTENT_TYPE);
}
public Map getAllHeaders() {
return headerMap;
}
}
java socket第三方库_Java基于Socket实现HTTP下载客户端相关推荐
- java socket第三方库_Java Socket类库 Java Sockets
软件介绍 Java Sockets is a class library implementing a subset of the C++ Sockets library, and is based ...
- Java常用第三方库大全西安尚学堂
Java常用第三方库大全 一.JAVA核心扩展 JAVA的标准库虽然提供了那些最基本的数据类型操作方法,但仍然对一些常见的需求场景,缺少实用的工具类.而另一些则是JAVA标准库本身不够完善,需要第三方 ...
- java http客户端实现_Java基于Socket实现HTTP下载客户端
没有借助任何第三方库,完全基于JAVA Socket实现一个最小化的HTTP文件下载客户端.完整的演示如何通过Socket实现下载文件的HTTP请求(request header)发送如何从Socke ...
- java socket 传输压缩文件_java基于socket传输zip文件功能示例
本文实例讲述了java基于socket传输zip文件的方法.分享给大家供大家参考,具体如下: 服务器端程序: import java.io.*; import java.net.*; import j ...
- socket java 客户端_Java基于socket实现的客户端和服务端通信功能完整实例
本文实例讲述了Java基于socket实现的客户端和服务端通信功能.分享给大家供大家参考,具体如下: 以下代码参考马士兵的聊天项目,先运行ChatServer.java实现端口监听,然后再运行Chat ...
- java socket gui登录_java的socket服务端的GUI
这几天做了一个基于socket的宠物商店程序,其中服务端的图形化界面问题困扰了很久.今天终于解决,因此也对多线程有了更好的理解. 想很多新手一样,我其实犯了一个错误. 由于soket服务端端口监听用的 ...
- java tcp ip通信_Java中Socket实现TCP/IP协议的通信
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的. Jav ...
- java socket 阻塞模式_Java中Socket Read阻塞问题
本人来说并不熟悉JAVA语言,只是近期在分析某个简单的java agent程序时,根据对应的代码写了一个对接的程序,两者之间是典型的C/S socket编程.客户端在向服务端发送相应的指令后,服务端( ...
- java socket资源释放_java基础--socket
(1) 一.网络:将不同区域的计算机连接到一起 局域网 城域网 互联网 二.地址:IP地址 确定网络上 一个绝对地址 |位置 --->房子的地址 三.端口号: 区分计算机软件的 -->房子 ...
- java判断socket是否连接_java判断socket是否连接
在socket类中有一个方法sendUrgentData,它会往输出流发送一个字节的数据,只要对方Socket的SO_OOBINLINE属性没有打开,就会自动舍弃这个字节(在Java 中是抛出异常), ...
最新文章
- SMW0上传模板下载到本地
- 字符串-定义和基本使用
- 黑白树(牛客网+树形dp)
- php改成IP连接数据库,thinkphp,pdo连接数据库,host自动被替换成了本机ip
- Android 编码规范:(七)避免使用终结方法
- MySQL Root密码丢失解决方法总结
- centos7更换源
- 【linux笔记】linux权限命令
- java框架_Java 中几种常用的 RPC 框架介绍
- u盘装linux fail load,安装ubuntu18.04报:failed to load ldlinux.c32的问题及解决步骤
- selenium模拟键盘操作大全
- 制作好的种子怎么上传服务器,用BT如何上传自己的文件?
- android float 百分比,如何在android中计算百分比
- 压缩包已损坏或压缩格式未知无法打开 的解决办法
- zend php5.2,phpstudy v8 php5.2安装zend
- win10修改user用户名,完美解决,亲试无bugs
- ZigBee网络路由算法设计
- 三角形的平移、旋转,在VC上实现(矩阵的应用)
- 滴滴出行 DoKit 2.0 - 泛前端开发者的百宝箱
- 大学生新生报到管理系统
热门文章
- 请求头User-Agent作用?
- Python NLP完整项目实战教程(1)
- net.sf.json与fastjson两种jar包的使用
- 第八周项目4-个人所得税计算器
- SQL Server Collation介绍及其变更对数据的影响
- 没有与这些操作数匹配的运算符_【5min+】 这些C#的运算符您都认识吗?
- 郑州超级计算机叫什么,国家超级计算郑州中心通过验收 2020超级计算机行业发展策略...
- 万物皆可python_Python知识点合集,学完万物皆可爬
- PHP Mysql or条件排序问题
- 跑跑卡丁车rush服务器维护,跑跑卡丁车Rush+测试服