什么是IPV4,什么是IPV6:
  • 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)。
在IPv4地址出现之初,互联网还没有像今天这样引起商业轰动,大多数网络都是私有的,并且与世界上其他网络隔绝。当互联网爆发式增长,只有32位来识别一个独特的互联网地址感觉有点不够用,这让人们担心我们的IP地址会用完。在IPv4下,有232种可能的组合,提供了将近43亿个唯一地址。IPv6将其提升到2128亿个可能的组合。

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

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和URLConnection

URL类提供了多个构造器用于创建URL对象,一旦获得URL对象之后,就可以调用如下方法来访问该URL对应的资源:
  • 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;多线程下载文件示例的更多相关文章

  1. Java 网络编程:必知必会的 URL 和 URLConnection

    java.net.URL 类将 URL 地址进行了封装,并提供了解析 URL 地址的基本方法,比如获取 URL 的主机名和端口号.java.net.URLConnection 则代表了应用程序和 UR ...

  2. Java网络编程和NIO详解开篇:Java网络编程基础

    Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...

  3. Java网络编程基础(Netty预备知识)

    今天在家休息,闲来无事,写篇博客,陶冶下情操~~~ =================我是分割线================ 最近在重新学习Java网络编程基础,以便后续进行Netty的学习. 整 ...

  4. java网络编程基础——网络基础

    java网络编程 网络编程基础 1.常用的网络拓扑结构: 星型网络.总线网络.环线网络.树形网络.星型环线网络 2.通信协议的组成 通信协议通常由3部分组成: 语义部分:用于决定通信双方对话类型 语法 ...

  5. 【Java基础】Java网络编程基础知识

    什么是网络编程 网络编程是通过使用套接字来达到进程间通信目的,那什么是套接字呢?其实套接字是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的 ...

  6. java网络编程基础——基本网络支持

    基本网络支持 java.net包主要为网络编程提供支持. 1.InetAddress InetAddress类代表IP地址,还有两个子类:Inet4Address.Inet6Address. pack ...

  7. java网络编程基础

    前言 通过网络进行数据传输时,一般使用TCP/UDP进行数据传输.但是两个的区别就是TCP可靠,UDP不可靠.两个的共同之处就是都需要建立socket套接字,将IP地址和端口port进行绑定.但是服务 ...

  8. java网络编程基础——TCP网络编程一

    基于TCP协议的网络编程 TCP/IP协议是一种可靠的网络协议,它的通信的两端各自建立一个Socket,从而在通信的两端之间形成网络虚拟链路. Java使用Socket对象来代表两端的通信端口,并通过 ...

  9. JAVA网络编程基础知识

    网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯.网络编程中有两个主要的问题,一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输.在TCP/IP协 ...

随机推荐

  1. linux新增定时脚本

    crontab -e 然后新增: 0 * * * * sh /usr/local/redis/copy/redis_rdb_copy_hourly.sh 控制台回显"crontab:inst ...

  2. 提升 RTC 音频体验 - 从搞懂硬件开始

    前言 RTC(实时音视频通信)技术的快速发展,助力了直播.短视频等互动娱乐形式的普及:在全球疫情持续蔓延的态势下,云会议需求呈现爆发式增长,进一步推动了 RTC 行业的快速发展.为了给客户提供稳定可靠 ...

  3. SpringCloud微服务实战——搭建企业级开发框架(二十六):自定义扩展OAuth2实现短信验证码登录

    现在手机验证码登录似乎是每个网站必备的功能,OAuth2支持扩展自定义授权模式,前面介绍了如何在系统集成短信通知服务,这里我们进行OAuth2的授权模式自定义扩展,使系统支持短信验证码登录. 1.在g ...

  4. [Bzoj 1192][HNOI2006]鬼谷子的钱袋(二进制优化多重背包)

    (人生第一篇bzoj题解有点激动 首先介绍一下题目: 看它题目那么长,其实意思就是给定一个数a,求将其拆分成n个数,通过这n个数可以表示出1~a中所有数的方案中,求最小的n. 您看懂了嘛?不懂咱来举个 ...

  5. [SDOI2012] Longge 的问题

    题意 求\(\sum_{i}^{n} gcd(i,n)\) 想法 套路题 \(\sum_{i}^{n} gcd(i,n)\) \(=\) \(\sum_{i,i | n} i * phi(n/i)\) ...

  6. FESTUNG 模型介绍 — 2. 对流问题隐式求解

    FESTUNG 模型介绍 - 2. 对流问题隐式求解 1. 控制方程 对流问题的控制方程为 \[\partial_t C + \partial_x u^1 C + \partial_y u^2 C = ...

  7. STM32驱动直流电机的程序与电路设计(IR2110S自举电路+H桥+高级定时器和死区PWM)

    https://blog.csdn.net/geek_monkey/article/details/82079435

  8. void * 指针和const 指针

    1.void * 是不能进行运算的,例如void *p  p++; 这2个值是没有任何规律的. 2 .printf的时候打印void *p 指向的数据,必须强制类型转换,因为编译器不知道取地址多少位. ...

  9. Java 读取txt文件生成Word文档

    本文将以Java程序代码为例介绍如何读取txt文件中的内容,生成Word文档.在编辑代码前,可参考如下代码环境进行配置: IntelliJ IDEA Free Spire.Doc for Java T ...

  10. C语言中的字符和整数之间的转换

    首先对照ascal表,查找字符和整数之间的规律: ascall 控制字符  48  0  49  1  50  2  51  3  52  4  53  5  54  6  55  7  56  8 ...