java 网络编程基础 InetAddress类;URLDecoder和URLEncoder;URL和URLConnection;多线程下载文件示例
- IPv4使用32个二进制位在网络上创建单个唯一地址。IPv4地址由四个数字表示,用点分隔。每个数字都是十进制(以10为基底)表示的八位二进制(以2为基底)数字,例如:216.27.61.137。
- IPv6使用128个二进制位在网络上创建一个唯一地址。IPv6地址由八组十六进制(以16为基数)数字表示,这些数字由冒号分隔,如2001:cdba:0000:0000:0000:0000:0000:3257:9652所示。为了节省空间,通常省略包含所有零的数字组,留下冒号分隔符来标记空白(如2001:cdba::3257:9652)。
InetAddress
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException; /**
* @ClassName InetAddressExample
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/5/9.
*/
public class InetAddressExample {
public static void main(String[] args) throws IOException {
/**
* 创建InetAddress 实例getByName静态方法
*/
InetAddress ksyunAddr = InetAddress.getByName("www.ksyun.com");
/**
* 获取IP地址字符串
*/
System.out.println(ksyunAddr.getHostAddress());
/**
* 判断地址是否可达:isReachable
*/
System.out.println(ksyunAddr.isReachable(2000));
/**
* 获取本机IP InetAddress.getLocalHost()
*/
InetAddress localIPObj = InetAddress.getLocalHost();
System.out.println(localIPObj.getHostAddress());
//
//指定IP地址创建 InetAddress对象
InetAddress localIp = InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
}
}
URLDecoder和URLEncoder
public class UrlEncodeTest {
public static void main(String[] args) throws UnsupportedEncodingException {
String url = "https://www.baidu.com/狗逼/";
//转码
String encodeUrl = URLEncoder.encode(url,"utf-8");
System.out.println(encodeUrl); //https%3A%2F%2Fwww.baidu.com%2F%E7%8B%97%E9%80%BC%2F
//解码
String str = URLDecoder.decode(encodeUrl,"utf-8");
System.out.println(str);//https://www.baidu.com/狗逼/
}
}
URL和URLConnection
- String getFile(): 获取该URL资源名。
- String getHost(): 获取URL的主机名
- String getPath(): 获取该URL的路径部分
- int getPort(): 获取URL的端口号。
- String getProtocol(): 获取该URL的协议名称
- String getQuery() 获取该 URL 宇符串部分。
- URLConnection openConnection(): 返回一个URLConnection它代表了与该URL 所引用的远对象的连接。
- InputStream openStream() 打开与此URL连接,并返回一个用于读取该URL资源的 InputStream
多线程下载文件示例:
知识点:
- URL类openConnection() 所引用的远对象的连接; 对象的getContentLength方法获取响应头文件字节长度
- URL类openStream() 打开与此URL连接,并返回一个用于读取该URL资源的 InputStream
- RandomAccessFile类创建文件、预置文件大小、从任意位置读写文件
- 线程池:Executors.newCachedThreadPool() 获取ExecutorService线程池对象,submit 提交任务
- 线程池任务类实现 Runnable 接口,重写run() 方法定义任务细节。
设计思路:
- 获取到文件大小,设置线程数,计算每个线程下载文件的初始字节数和下载(保存)字节数,每个线程从网络get到的字节覆盖写入到本地预置文件的对应字节位置内。
代码示例(Range版):
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* @ClassName ThreadPoolMultiDownLoad
* @projectName: object1
* @author: Zhangmingda
* @description: 使用多线程线程池方式下载文件
* date: 2021/5/9.
*/
public class ThreadPoolMultiDownLoad {
/**
* 要下文件的url地址
*/
private String urlString;
/**
* 线程数
*/
private int threadNum;
/**
* 保存文件的目录
*/
private String saveDir;
/**
* 文件的大小
*/
private int fileSize;
/**
* 线程池
*/
private static ExecutorService threadPool = null; /**
* 下载类构造方法
* @param urlString 文件地址
* @param threadNum 线程数设置
* @param saveDir 本地文件保存目录
*/
public ThreadPoolMultiDownLoad(String urlString, int threadNum, String saveDir) {
this.urlString = urlString;
this.threadNum = threadNum;
this.saveDir = saveDir;
}
/**
* 创建线程池实例的方法,确保线程池为单例(多线程同时运行时使用同一个实例)
*/
private static ExecutorService getThreadPool(){
if (threadPool == null){
synchronized (ThreadPoolMultiDownLoad.class){
if (threadPool == null){
threadPool = Executors.newCachedThreadPool();
}
}
}
return threadPool;
}
/**
* 获取文件大小方法
*/
private int getFileSize(URL url) throws IOException {
return url.openConnection().getContentLength();
}
/**
* 并发用分块下载写入的类
*/
private class DownPart implements Runnable {
private int startByte;
private int threadDownSize;
private RandomAccessFile accessFile;
private URL url; /** 本线程运行所需担心
* @param startByte 下载起始字节
* @param threadDownSize 本线程下载字节量
* @param accessFile 本地写入文件
*/
public DownPart(int startByte, int threadDownSize, RandomAccessFile accessFile,URL url) {
this.startByte = startByte;
this.threadDownSize = threadDownSize;
this.accessFile = accessFile;
this.url = url;
}
//本线程运行方法
@Override
public void run() {
int readcount = 0;
InputStream inputStream = null;
//打开http输入流
try {
URLConnection conn = this.url.openConnection();
/**
* 设置每个请求字节范围
*/
conn.setRequestProperty("Range","bytes=" + startByte + "-" + (startByte + threadDownSize));
inputStream = conn.getInputStream();
// //跳过非本线程需要下载的字节
// inputStream.skip(startByte);
/**
* 将本线程需要下载的字节写到本地文件中
*/
byte[] buffer = new byte[10240];
int len = 0;
while (readcount < this.threadDownSize && (len = inputStream.read(buffer)) != -1 ){
accessFile.write(buffer,0,len);
readcount += len;
}
System.out.println(Thread.currentThread().getName() + "下载写入了" + readcount + "字节的数据" );
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (inputStream != null){inputStream.close(); }
if (accessFile != null){accessFile.close();} } catch (IOException e) {
e.printStackTrace();
}
} }
}
/**
* 下载文件方法
*/
public void download() throws IOException {
/**
* URL构造
*/
URL url = new URL(this.urlString);
/**
* 文件大小获取
*/
this.fileSize = getFileSize(url);
/**
* 每个线程下载的文件大小:由于fileSize总大小除以线程数量后,得出的小数部分会省略,所以每个线程多下载一字节
*/
int threadDownSize = this.threadNum == 1 ? this.fileSize : (this.fileSize / this.threadNum + 1);
/**
* 获取文件名
*/
String[] strings = this.urlString.split("/");
String fileName = strings[strings.length-1];
/**
* 本地预创建文件并预置文件大小
*/
String saveFilePath = this.saveDir + "/" + fileName;
System.out.println(saveFilePath);
RandomAccessFile accessFile = new RandomAccessFile(saveFilePath,"rw");
accessFile.setLength(this.fileSize);
accessFile.close();
/**
* 循环启动线程,分块写入到文件
*/
url = new URL(urlString);
for (int i=0; i<this.threadNum; i++){
//文件起始写入的位置
int startByte = i * threadDownSize;
//打开文件将文件指针移到该线程应该覆盖写入本地文件字节位置
RandomAccessFile randomAccessFile = new RandomAccessFile(saveFilePath,"rw");
randomAccessFile.seek(startByte); getThreadPool().submit(new DownPart(startByte,threadDownSize,randomAccessFile,url));
}
getThreadPool().shutdown();
} /**
* @param args
*/
public static void main(String[] args) throws IOException {
String ks3utilUrl = "https://ks3-cn-beijing.ksyun.com/ks3-import/KS3-import-tool-2.1.4-dist.zip";
new ThreadPoolMultiDownLoad(ks3utilUrl,4,"网络编程/src").download();
}
}
java 网络编程基础 InetAddress类;URLDecoder和URLEncoder;URL和URLConnection;多线程下载文件示例的更多相关文章
- Java 网络编程:必知必会的 URL 和 URLConnection
java.net.URL 类将 URL 地址进行了封装,并提供了解析 URL 地址的基本方法,比如获取 URL 的主机名和端口号.java.net.URLConnection 则代表了应用程序和 UR ...
- Java网络编程和NIO详解开篇:Java网络编程基础
Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...
- Java网络编程基础(Netty预备知识)
今天在家休息,闲来无事,写篇博客,陶冶下情操~~~ =================我是分割线================ 最近在重新学习Java网络编程基础,以便后续进行Netty的学习. 整 ...
- java网络编程基础——网络基础
java网络编程 网络编程基础 1.常用的网络拓扑结构: 星型网络.总线网络.环线网络.树形网络.星型环线网络 2.通信协议的组成 通信协议通常由3部分组成: 语义部分:用于决定通信双方对话类型 语法 ...
- 【Java基础】Java网络编程基础知识
什么是网络编程 网络编程是通过使用套接字来达到进程间通信目的,那什么是套接字呢?其实套接字是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的 ...
- java网络编程基础——基本网络支持
基本网络支持 java.net包主要为网络编程提供支持. 1.InetAddress InetAddress类代表IP地址,还有两个子类:Inet4Address.Inet6Address. pack ...
- java网络编程基础
前言 通过网络进行数据传输时,一般使用TCP/UDP进行数据传输.但是两个的区别就是TCP可靠,UDP不可靠.两个的共同之处就是都需要建立socket套接字,将IP地址和端口port进行绑定.但是服务 ...
- java网络编程基础——TCP网络编程一
基于TCP协议的网络编程 TCP/IP协议是一种可靠的网络协议,它的通信的两端各自建立一个Socket,从而在通信的两端之间形成网络虚拟链路. Java使用Socket对象来代表两端的通信端口,并通过 ...
- JAVA网络编程基础知识
网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯.网络编程中有两个主要的问题,一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输.在TCP/IP协 ...
随机推荐
- javascript-初级-day06作用域、JS预解析机制
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- Kubernetes Deployment 最佳实践
零.示例 首先给出一个 Deployment+HPA+ PodDisruptionBudget 的完整 demo,后面再详细介绍其中的每一个部分: apiVersion: apps/v1 kind: ...
- OI省选算法汇总及学习计划(转)
1.1 基本数据结构 数组(√) 链表(√),双向链表(√) 队列(√),单调队列(√),双端队列(√) 栈(√),单调栈(√) 1.2 中级数据结构 堆(√) 并查集与带权并查集(√) hash 表 ...
- SA 复习笔记
大家好,由于蒟蒻 tzc 最近被动态点分治这个学也学不会的毒瘤玩意儿虐得不轻,所以就准备换换脑筋来 Van 同样学也学不会的后缀数组了. 考虑一个非常经典的问题:[模板]后缀排序. 一些定义(very ...
- WPS for Linux 字体配置(字体缺失解决办法)
WPS for Linux 字体配置(字体缺失解决办法) 1. 背景 有些linux装完wps后提示"部分字体无法显示"或"some formula symbols mi ...
- 【GS文献】全基因组选择模型研究进展及展望
目录 1. GS概况 2. GS模型 1)直接法 GBLUP 直接法的模型改进 ①单随机效应 ②多随机效应 2)间接法 间接法模型 基于间接法的模型改进 3. GS模型比较 模型比较结论 4.问题及展 ...
- 强化学习实战 | 自定义Gym环境之井字棋
在文章 强化学习实战 | 自定义Gym环境 中 ,我们了解了一个简单的环境应该如何定义,并使用 print 简单地呈现了环境.在本文中,我们将学习自定义一个稍微复杂一点的环境--井字棋.回想一下井字棋 ...
- Go Robot
1 <html> 2 <meta http-equiv="Content-Type" content="text/html; charset=utf-8 ...
- [PE]结构分析与代码实现
PE结构浅析 知识导向: 程序最开始是存放在磁盘上的,运行程序首先需要申请4GB的内存,将程序从磁盘copy到内存,但不是直接复制,而是进行拉伸处理. 这也就是为什么会有一个文件中地址和一个Virtu ...
- Excel 数据验证:分类选择及输入限制
几个简单设置让你的数据不再出错 如何快速选择某一大类中的细分小类 多级菜单 注意:引用可以创建二级目录,但是引用前应先用公式定义名称,然后引用,引用只能在本sheet操作.