什么是IPV4,什么是IPV6:
在IPv4地址出现之初,互联网还没有像今天这样引起商业轰动,大多数网络都是私有的,并且与世界上其他网络隔绝。当互联网爆发式增长,只有32位来识别一个独特的互联网地址感觉有点不够用,这让人们担心我们的IP地址会用完。在IPv4下,有232种可能的组合,提供了将近43亿个唯一地址。IPv6将其提升到2128亿个可能的组合。
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用来完成普通字符串和applicationl/x-www-form-urlencoded MIME 字符串之间的相互转换。
比如我们在百度上搜索一个“李一桐”,wd对应的字符会变成:“%E6%9D%8E%E4%B8%80%E6%A1%90”,其实这个东西就是我们的 pplicationl/x-www-form-urlencoded MIME 字符串。
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类提供了多个构造器用于创建URL对象,一旦获得URL对象之后,就可以调用如下方法来访问该URL对应的资源:
知识点:
URL类openConnection() 所引用的远对象的连接; 对象的getContentLength方法获取响应头文件字节长度
URL类openStream() 打开与此URL连接,并返回一个用于读取该URL资源的 InputStream
RandomAccessFile类创建文件、预置文件大小、从任意位置读写文件
线程池:Executors.newCachedThreadPool() 获取ExecutorService线程池对象,submit 提交任务
线程池任务类实现 Runnable 接口,重写run() 方法定义任务细节。
设计思路:
代码示例(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();
}
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章