1️⃣网络编程概述

  • Java是Internet 上的语言,它从语言级上提供了对网络应用程序的支持,程序员能够很容易开发常见的网络应用程序。
  • Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在Java 的本机安装系统里,由JVM 进行控制。并且Java 实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境。
  • 计算机网络:
    把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息、共享硬件、软件、数据信息等资源。
  • 网络编程的目的:
    直接或间接地通过网络协议与其它计算机实现数据交换,进行通讯。
  • 网络编程中有两个主要的问题:
    1. 如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
    2. 找到主机后如何可靠高效地进行数据传输

2️⃣网络通信要素概述

  • 通信双方地址
  1. IP
  2. 端口号
  • 一定的规则(即:网络通信协议。有两套参考模型)
    • OSI参考模型:模型过于理想化,未能在因特网上进行广泛推广
    • TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。
  • 网络通信协议
    在这里插入图片描述
    在这里插入图片描述
1
2
3
4
5
6
7
8
9
10
11
/**
* 一、网络编程中有两个主要的问题:
* 1.如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
* 2.找到主机后如何可靠高效地进行数据传输
*
* 二、网络编程中的两个要素:
* 1.对应问题一:IP和端口号
* 2.对应问题二:提供网络通信协议:TCP/IP参考模型(应用层、传输层、网络层、物理+数据链路层)
*/

12345678910

3️⃣信要素1:IP和端口号

IP的理解与InetAddress类的实例化

  • IP 地址:InetAddress
    • 唯一的标识Internet 上的计算机(通信实体)
    • 本地回环地址(hostAddress):127.0.0.1 主机名(hostName):localhost
    • IP地址分类方式1:IPV4和IPV6
      • IPV4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。以点分十进制表示,如192.168.0.1
      • IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
    • IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)。192.168.开头的就是私有地址,范围即为192.168.0.0–192.168.255.255,专门为组织机构内部使用
    • 特点:不易记忆
  • Internet上的主机有两种方式表示地址:
    • 域名(hostName):www.wjiangquan.top
    • IP地址(hostAddress):202.108.35.210
  • InetAddress类主要表示IP地址,两个子类:Inet4Address、Inet6Address。
  • InetAddress类对象含有一个Internet主机地址的域名和IP地址:www.wjiangquan.top
  • 和202.108.35.210。
  • 域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS)负责将域名转化成IP地址,这样才能和主机建立连接。-------域名解析
    在这里插入图片描述
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package hxut;

/**
* @author weijiangquan
* @date 2022/5/8 -23:17
* @Description
*
*
*/

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
* 一、网络编程中有两个主要的问题:
* 1.如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
* 2.找到主机后如何可靠高效地进行数据传输
*
* 二、网络编程中的两个要素:
* 1.对应问题一:IP和端口号
* 2.对应问题二:提供网络通信协议:TCP/IP参考模型(应用层、传输层、网络层、物理+数据链路层)
*
*
* 三、通信要素一:IP和端口号
*
* 1. IP:唯一的标识 Internet 上的计算机(通信实体)
* 2. 在Java中使用InetAddress类代表IP
* 3. IP分类:IPv4 和 IPv6 ; 万维网 和 局域网
* 4. 域名:www.baidu.com www.mi.com www.sina.com www.jd.com
* www.vip.com
* 5. 本地回路地址:127.0.0.1 对应着:localhost
*
* 6. 如何实例化InetAddress:两个方法:getByName(String host) 、 getLocalHost()
* 两个常用方法:getHostName() / getHostAddress()
*
* 7. 端口号:正在计算机上运行的进程。
* 要求:不同的进程有不同的端口号
* 范围:被规定为一个 16 位的整数 0~65535。
*
* 8. 端口号与IP地址的组合得出一个网络套接字:Socket
*/
public class InetAddressTest {
public static void main(String[] args) {
try {
InetAddress inet1 = InetAddress.getByName("192.168.10.14");
System.out.println(inet1);
//run result=>/192.168.10.14

InetAddress inet2= InetAddress.getByName("www.wjiangquan.top");
System.out.println(inet2);
//run result=>www.wjiangquan.top/47.94.10.92

InetAddress inet3= InetAddress.getByName("www.baidu.com");
System.out.println(inet3);
//run result=>www.wjiangquan.top/47.94.10.92(这个有点强)(小工具)
InetAddress inet4 = InetAddress.getByName("127.0.0.1");
System.out.println(inet4);
//run result=>/127.0.0.1 (这个目前感觉不到获取的价值)

//获取本地的ip
InetAddress inet5 = InetAddress.getLocalHost();
System.out.println(inet5); //run result=>DESKTOP-40FEAVL/192.168.167.188


//gteHostName
System.out.println(inet2.getHostName()); //run result=>www.wjiangquan.top
//getHostAddress
System.out.println(inet2.getHostAddress()); //run result=>47.94.10.92
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}


端口号的理解

  • 端口号标识正在计算机上运行的进程(程序)
    • 不同的进程有不同的端口号
    • 被规定为一个16 位的整数0~65535
    • 端口分类
      • 公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
      • 注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。
      • 动态/私有端口:49152~65535
  • 端口号与IP地址的组合得出一个网络套接字:Socket

在这里插入图片描述

4️⃣通信要素2:网络协议

  • 网络通信协议
    计算机网络中实现通信必须有一些约定,即通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。
  • 问题:网络协议太复杂
    计算机网络通信涉及内容很多,比如指定源地址和目标地址,加密解密,压缩解压缩,差错控制,流量控制,路由控制,如何实现如此复杂的网络协议呢?
  • 通信协议分层的思想
    在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展。

TCP和UDP网络通信协议的对比

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

5️⃣TCP网络编程

1、例题1
客户端发送信息给服务端,服务端将数据显示在控制台上

例题1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package hxut;

import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

/**
* @author weijiangquan
* @date 2022/5/9 -11:33
* @Description
*
* Tcp的网络编程
* 例子1:客户端发送信息给服务端,服务器将数据显示在控制台上
*/
public class TCPTest {

// 先启动服务端,在启动客户端

//客户端
@Test
public void client(){

Socket socket = null;
OutputStream os = null;
try {
//1.创建Socket对象,指明服务器端的ip和端口号
InetAddress inet = InetAddress.getByName("127.0.0.1");

socket = new Socket(inet,8899);

//2获取一个输出流,用于输出数据
os = socket.getOutputStream();

//3.用输出流写出数据
os.write("你好,我是客户端".getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {
//4.关闭资源
if( os != null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


// 服务端
@Test
public void test1(){
ServerSocket ss = null;
Socket socket = null;
InputStream is= null;
ByteArrayOutputStream baos = null; //ByteArrayOutputStream这个会在内部自动扩
try {
//1. 创建服务器端的serverSocket,指明自己的端口号
ss = new ServerSocket(8899);
//2.调用accept()表示接收来自客户端的socket
socket = ss.accept();
//3.获取一个输入流
is = socket.getInputStream();

// 不建议这样写,可能会有乱码
/*byte[] bytes = new byte[1024];
int len;
while ((len = is.read(bytes))!=-1){
String str = new String(bytes,0,len);
System.out.println(str);
}*/
//4.读取输入流中的数据
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[5];
int len;
while ((len = is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());

System.out.println("收到了来自于"+socket.getInetAddress()+"地址");
} catch (IOException e) {
e.printStackTrace();
}finally {
//5关闭资源
if(baos!=null){
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ss != null){
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}

}


在这里插入图片描述

2、例题2
客户端发送文件给服务端,服务端将文件保存在本地。

⭐例题2

注意点:InputStream本身是抽象类,不可以实例化对象,(需要重写read()方法。

1
2
3
4
5
6
InputStream is=new InputStream() {
@Override
public int read() throws IOException {
return 0;
}
};

下面代码中使用InputStream is =null;(len=is.read(buffer))!=-1

这里面的is 指向的是scoket.getInputStream() 返回的对象,通过源码发现该对象已经重载过read() 方法,因此可以使用is.read();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public InputStream getInputStream() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!isConnected())
throw new SocketException("Socket is not connected");
if (isInputShutdown())
throw new SocketException("Socket input is shutdown");
InputStream is = null;
try {
//注意这里************************************
is = AccessController.doPrivileged(
new PrivilegedExceptionAction<>() {
public InputStream run() throws IOException {
return impl.getInputStream();
}
});
} catch (java.security.PrivilegedActionException e) {
throw (IOException) e.getException();
}
return is;
}

Answer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package pers.dhx_.java0623;

import org.junit.jupiter.api.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
* @author Dhx_
* @className TCPTest3
* @description TODO
* @date 2022/6/23 16:00
*/
public class TCPTest3 {
@Test
public void client() { //客户端
Socket socket = null;
FileInputStream fis = null;
OutputStream os = null;
ByteArrayOutputStream baos = null;
InputStream is = null;
try {
socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
os = socket.getOutputStream();
fis = new FileInputStream(new File("E:\\vscode_background\\07af42bd8clmWoE.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
socket.shutdownOutput();//关闭数据的输出

//接收来自于服务器端的数据,并显示到控制台上
is = socket.getInputStream();
baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[1024];
int len1;
//注意这个地方使用的是is.read(),使用fis.read()无法读取到数据
while ((len1 = is.read(buffer2)) != -1) {
baos.write(buffer2, 0, len1);
}
System.out.println(baos.toString());

} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (socket != null) {
socket.close();
}
if (baos != null) {
baos.close();
}
if (fis != null) {
fis.close();
}
if (os != null) {
os.close();
}
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

@Test
public void server() { //服务端
ServerSocket ss = null;
FileOutputStream fos = null;
InputStream is = null;
Socket socket = null;
try {
ss = new ServerSocket(9090);
socket = ss.accept();
is = socket.getInputStream();
fos = new FileOutputStream("TDPTest.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("图片传输完成");
//服务器端给客户端反馈
OutputStream os = socket.getOutputStream();
os.write("图片已收到".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
if (is != null) {
is.close();
}
if (ss != null) {
ss.close();
}
if (socket != null) {
socket.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

3、例题

从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端。 并关闭相应的连接。

例题3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package hxut;

import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
* @author weijiangquan
* @date 2022/5/9 -16:19
* @Description
*/
public class TcpTest3 {


/**
* 这里涉及到的异常,应该使用try-catch-finally处理
* @throws IOException
*/
@Test
public void test() throws IOException {
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
OutputStream os = socket.getOutputStream();
FileInputStream fis = new FileInputStream(new File("爱情与友情.jpg"));
byte[] buffer = new byte[1024];
int len;
while((len = fis.read(buffer)) != -1){
os.write(buffer,0,len);
}
//关闭数据的输出
socket.shutdownOutput();

//5.接收来自于服务器端的数据,并显示到控制台上
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bufferr = new byte[20];
int len1;
while((len1 = is.read(buffer)) != -1){
baos.write(buffer,0,len1);
}
System.out.println(baos.toString());

fis.close();
os.close();
socket.close();
baos.close();
}

/**
* 这里涉及到的异常,应该使用try-catch-finally处理
* @throws IOException
*/
@Test
public void test2() throws IOException {
ServerSocket ss = new ServerSocket(9090);
Socket socket = ss.accept();
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream(new File("爱情与友情4.jpg"));
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) != -1){
fos.write(buffer,0,len);
}

System.out.println("图片传输完成");

//6.服务器端给予客户端反馈
OutputStream os = socket.getOutputStream();
os.write("你好,照片我已收到,风景不错!".getBytes());

fos.close();
is.close();
socket.close();
ss.close();
os.close();
}
}




6️⃣UDP网络编程

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package pers.dhx_.java0623;

import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
* @author Dhx_
* @className UDPTESt
* @description TODO
* @date 2022/6/23 18:01
*/
public class UDPTest {
@Test
public void test() throws IOException { //发送端
DatagramSocket socket = new DatagramSocket();
String str = "我是UDP方式发送的导弹";
byte[] data = str.getBytes();
InetAddress inet = InetAddress.getLocalHost();
DatagramPacket datagramPacket = new DatagramPacket(data, 0, data.length, inet, 9999);
socket.send(datagramPacket);
socket.close();
}

//接收端
@Test
public void test1() throws IOException {
DatagramSocket socket = new DatagramSocket(9999);
byte[] buffer = new byte[100];
DatagramPacket datagramPacket = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(datagramPacket);
System.out.println(new String(datagramPacket.getData(), 0, datagramPacket.getLength()));
socket.close();
}
}

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051

7️⃣URL编程

🎈URL

image-20220724180512400

URL类构造器

![image-20220623180946275](C:\Users\lenovo\Desktop\Java\SUMMER_JAVA\JavaSe _Note\image\image-20220623180946275.png)

URL类常用方法

image-20220724180517245

URL的理解与实例化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package hxut;

/**
* @author weijiangquan
* @date 2022/5/9 -16:56
* @Description
*/

import java.net.MalformedURLException;
import java.net.URL;

/**
* URL网络编程
* 1.URL:统一资源定位符,对应着互联网的某一资源地址
* 2.格式:
* http://127.0.0.1:8080/work/164.jpg?username=subei
* 协议 主机名 端口号 资源地址 参数列表
*/
public class URLTest {
public static void main(String[] args) throws MalformedURLException {


URL url = new URL(" http://127.0.0.1:8080/work/164.jpg?username=subei");

// public String getProtocol( ) 获取该URL的协议名
System.out.println(url.getProtocol());
// public String getHost( ) 获取该URL的主机名
System.out.println(url.getHost());
// public String getPort( ) 获取该URL的端口号
System.out.println(url.getPort());
// public String getPath( ) 获取该URL的文件路径
System.out.println(url.getPath());
// public String getFile( ) 获取该URL的文件名
System.out.println(url.getFile());
// public String getQuery( ) 获取该URL的查询名
System.out.println(url.getQuery());

}

}


🍅针对HTTP协议的URLConnection类

URL的方法 openStream():能从网络上读取数据

若希望输出数据,例如向服务器端的 CGI (公共网关接口-Common Gateway Interface-的简称,是用户浏览器和服务器端的应用程序进行连接的接口)程序发送一些数据,则必须先与URL建立连接,然后才能对其进行读写,此时需要使用URLConnection 。

URLConnection:表示到URL所引用的远程对象的连接。当与一个URL建立连接时,首先要在一个 URL 对象上通过方法 openConnection() 生成对应的 URLConnection对象。如果连接过程失败,将产生IOException.

URL netchinaren = new URL ("http://www.atguigu.com/index.shtml");

URLConnectonn u = netchinaren.openConnection( );

💃通过URLConnection对象获取的输入流和输出流,即可以与现有的CGI程序进行交互。

public Object getContent( ) throws IOException

public int getContentLength( )

public String getContentType( )

public long getDate( )

public long getLastModified( )

public InputStream getInputStream( )throws IOException

public OutputSteram getOutputStream( )throws IOException

URL网络编程实现Tomcat服务端数据下载(p630)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class URLTest1 {
public static void main(String[] args) {
HttpURLConnection urlConnection = null;
InputStream is = null;
FileOutputStream fos = null;
try {
URL url = new URL("http://127.0.0.1:8080/work/164.jpg");

urlConnection = (HttpURLConnection) url.openConnection();

urlConnection.connect();

is = urlConnection.getInputStream();
fos = new FileOutputStream("day10\\1643.jpg");

byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) != -1){
fos.write(buffer,0,len);
}

System.out.println("下载完成");
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(urlConnection != null){
urlConnection.disconnect();
}
}
}
}


URI、URL和URN的区别

  • URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。而URL是uniform resource locator,统一资源定位符,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。而URN,uniform resource name,统一资源命名,是通过名字来标识资源,比如mailto:java-net@java.sun.com。也就是说,URI是以一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式。URL和URN都是一种URI。
  • 在Java的URI中,一个URI实例可以代表绝对的,也可以是相对的,只要它符合URI的语法规则。而URL类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的。