网络编程笔记

网络编程


1.1、概述

计算机网络:

计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

网络编程的目的:

无线电台、传播交流信息、数据交换、通信

想打到这个效果需要什么:

1、如何准确的定位网络上的一台主机?

IP: 端口

2、找到了主机如何传输?

javaweb:网页编程 B/S 架构

网络编程:TCP/IP C/S 架构


1.2、网络通信的要素

网络编程摘有两个主要的问题

  • 如何准确的定位网络上的一台或者多台主机

  • 找到主机后如何通信

网络编程中的要素

  • IP 和端口
  • 网络通信协议 udp、tcp

万物皆对象


1.3、IP

IP 地址: InetAddress

java.net.InetAddress 包

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
package com.haibara.lesson01;

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

//测试IP
public class TestInetAddress {
public static void main(String[] args) throws UnknownHostException {
try{
//查询本机地址
InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
System.out.println(inetAddress1);
InetAddress inetAddressLocalhostByName = InetAddress.getByName("localhost");
System.out.println(inetAddressLocalhostByName);
InetAddress inetAddressLocalhost = InetAddress.getLocalHost();
System.out.println(inetAddressLocalhost);
//查询百度地址
InetAddress inetAddress2 = InetAddress.getByName("baidu.com");
System.out.println(inetAddress2);
//常用方法
System.out.println(inetAddress2.getHostAddress());//IP
System.out.println(inetAddress2.getHostName());//域名
}catch (UnknownHostException e){
e.printStackTrace();
}
}
}
1
2
3
4
5
6
/127.0.0.1
localhost/127.0.0.1
Haibara/192.168.64.1
baidu.com/220.181.38.251
220.181.38.251
baidu.com

1.4、端口

  • 范围:0-65535
  • TCP、UDP:单协议下端口不可冲突
  • 端口分类
    • 公有端口:0-1023
    • 程序注册端口:1024-49151
    • 动态、私有:49152-65535
1
netstat -ano #查看所有的端口
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.haibara.lesson01;

import java.net.InetSocketAddress;

public class TestInetSocketAddress {
public static void main(String[] args) {
InetSocketAddress inetSocketAddress = new InetSocketAddress("192.168.123.1", Integer.parseInt("80"));
System.out.println(inetSocketAddress.getAddress());
System.out.println(inetSocketAddress.getHostName());
System.out.println(inetSocketAddress.getPort());
System.out.println(inetSocketAddress.toString());
}
}
1
2
3
4
/192.168.123.1
MI-3.lan
80
MI-3.lan/192.168.123.1:80

1.5 通信协议

简单来说就是约定好说什么话

TCP/IP 协议

TCP:相当于打电话

UDP:相当于发短信


1.6、TCP

客户端

1、连接服务器 Socket

2、发送消息

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
package com.haibara.lesson02;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

//服务端
public class TcpServerDemo01 {
public static void main(String[] args) throws IOException {
Socket socket = null;
ServerSocket serverSocket = null;
InputStream inputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
//创建一个地址
serverSocket = new ServerSocket(12233);
//等待客户端连接
socket = serverSocket.accept();
//读取客户端信息
inputStream = socket.getInputStream();
//管道流
byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
byteArrayOutputStream.write(buffer, 0, len);
}
System.out.println(byteArrayOutputStream.toString());
}catch (Exception e){
e.printStackTrace();
}finally {
if (byteArrayOutputStream != null){
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

服务端

1、建立服务的端口 ServerSocket

2、等待用户的链接 Accept

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
package com.haibara.lesson02;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;

//客户端
public class TcpClientDemo01 {
public static void main(String[] args) {
OutputStream outputStream = null;
Socket socket = null;
try {
//得到一个地址
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
int port = 12233;
//连接地址
socket = new Socket(serverIP, port);
//发送消息
outputStream = socket.getOutputStream();
outputStream.write("Hello World".getBytes(StandardCharsets.UTF_8));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

1.7、文件上传

服务端

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
package com.haibara.lesson02;

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

public class TcpServerDemo02 {
public static void main(String[] args) throws IOException {
//创建服务
ServerSocket serverSocket = new ServerSocket(12233);
//监听客户端连接
Socket socket = serverSocket.accept();
//获取输入流
InputStream is = socket.getInputStream();
//文件输出
FileOutputStream fos = new FileOutputStream(new File("new_car.jpeg"));
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
//通知客户接受完成
OutputStream os = socket.getOutputStream();
os.write("finish".getBytes());
//关闭资源
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}

客户端

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 com.haibara.lesson02;

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

public class TcpClientDemo02 {
public static void main(String[] args) throws Exception {
//创建socket连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),12233);
//创建一个输出流
OutputStream os = socket.getOutputStream();
//读取文件
FileInputStream fis = new FileInputStream(new File("car.jpeg"));
//写出文件
byte[] buffer = new byte[1024];
int len;
while ((len=fis.read(buffer))!=-1){
os.write(buffer,0,len);
}
//通知服务器发送结束
socket.shutdownOutput();
//确定服务器接受完成才断开
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[1024];
int len2;
while ((len2=is.read(buffer2))!=-1){
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
//关闭资源
baos.close();
is.close();
fis.close();
os.close();
socket.close();

}
}

这里的流程就是先创建一个服务,就下了对服务进行监听,等待客户端的回应

客户端就连接到服务端,在创建一个输出流已向服务端发送流,在流创建好后开始读取文件,将文件转成文件输出流,接着就通知服务器发送结束了

服务器监听到客户端发送来的流开始读取流,客户端发送到输出流到了服务端就是输入流,将输入流写入到文件流,这就完成了文件的保存,在接收完成后通知客户端我已接收完成

在得到服务端回应已经接收完毕后双方开始断开连接


1.8、Tomcat

JDK 配置

在 Tomcat 配置前需要把 Jdk 配置好,此处是 centos7 环境下的配置方法

其实 jdk 的配置有比较简单的方法,那就是使用 yum 命令安装

在 [Oracle 官网](Java Archive Downloads - Java SE 8 (oracle.com)) 或者第三方网站上下载好 Jdk 的 RPM 包,再把 RPM 包传到 Linux 服务器上,或者直接在服务器上下载也可以

在下载好 jdk 的安装包后使用

1
yum -y localinstall jdk-8u202-linux-x64.rpm

查询 jdk 是否安装完成

1
java -version

在命令行有显示 jdk 版本即可

Tomcat 配置

接下来是配置 Tomcat 的环节

首先需要将 Tomcat 的文件放到服务器上,将文件解压出来(基础命令不做展示了)

接下来便是防火墙的设置

1
2
3
4
firewall-cmd --add-port=8080/tcp --permanent 
systemctl restart firewalld.service
firewall-cmd --reload
# 防火墙放行8080端口,重启防火墙,重新加载防火墙规则

设置 Tomcat 为服务

1
vim /usr/lib/systemd/system/tomcat9.service

在文件中写入内容

1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=Tomcat8
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking

ExecStart=/usr/tomcat/bin/startup.sh
ExecReload=/usr/tomcat/bin/startup.sh
ExecStop=/usr/tomcat/bin/shutdown.sh

[Install]
WantedBy=multi-user.target

服务已经写好,开启服务并启动 Tomcat

1
2
systemctl enable tomcat9
systemctl start tomcat9

22BA35A538AAAE290FDD799445D717F0

通过 IP 即可访问到 Tomcat 的默认页面


1.10、UDP 循环发送和循环接收

发送方 ——sender

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
package com.haibara.chat;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

/**
* @package: com.haibara.chat
* @className: UdpSender
* @author: Haibara
* @description: Udp聊天发送方(角色1)
*/
public class UdpSender {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
//准备数据
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
String data = reader.readLine();
if(data.equals("Bye")){
break;
}
byte[] bytes = data.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress("localhost",6666));
socket.send(packet);
}
socket.close();
}
}

接收方 ——receiver

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
package com.haibara.chat;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

/**
* @package: com.haibara.chat
* @className: UdpReceive
* @author: Haibara
* @description: Udp聊天接收方(角色2)
*/
public class UdpReceive {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while (true){
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data,0,data.length);
socket.receive(packet);
//判断断开连接
byte[] bytes = packet.getData();
String receiveData = new String(bytes,0,bytes.length);
System.out.println(receiveData);
if(receiveData.equals("Bye")){
break;
}
}
socket.close();
}
}

这主要是把发送消息和接收消息做好,接下来就会做互相发送消息的部分


1.11、多线程实现在线聊天

发送类

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
package com.haibara.chat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

/**
* @projectName: study
* @package: com.haibara.chat
* @className: TalkSend
* @author: Haibara
* @description: 负责发送消息
*/
public class TalkSend implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIP;
private int toPort;

public TalkSend(int fromPort, String toIP, int toPort) {
this.fromPort = fromPort;
this.toIP = toIP;
this.toPort = toPort;
try {
socket = new DatagramSocket(fromPort);
reader = new BufferedReader(new InputStreamReader(System.in));
}catch (Exception e){
e.printStackTrace();
}
}

@Override
public void run() {
//准备数据
while (true){
try {
String data = reader.readLine();
byte[] bytes = data.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress(this.toIP,this.toPort));
socket.send(packet);
if(data.equals("Bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}

}
socket.close();
}
}

接收类

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
package com.haibara.chat;

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

/**
* @projectName: study
* @package: com.haibara.chat
* @className: TalkReceive
* @author: Haibara
* @description: 负责接收消息
*/
public class TalkReceive implements Runnable{
DatagramSocket socket = null;
private int port;
private String fromMsg;

public TalkReceive(int port, String fromMsg){
this.port = port;
this.fromMsg = fromMsg;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}

@Override
public void run() {
while (true){
try {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data,0,data.length);
socket.receive(packet);
//判断断开连接
byte[] bytes = packet.getData();
String receiveData = new String(bytes,0,bytes.length);
System.out.println(fromMsg+":"+receiveData);
if(receiveData.equals("Bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}

多线程聊天

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.haibara.chat;

/**
* @projectName: study
* @package: com.haibara.chat
* @className: TalkStudent
* @author: Haibara
* @description: 白嫖怪和Up主的互动
*/
public class TalkStudent {
public static void main(String[] args) throws Exception {
new Thread(new TalkSend(7777,"localhost",9999)).start();
new Thread(new TalkReceive(8888,"白嫖怪")).start();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.haibara.chat;

/**
* @projectName: study
* @package: com.haibara.chat
* @className: TalkTeacher
* @author: Haibara
* @description: 白嫖怪和Up主的互动
*/
public class TalkTeacher {
public static void main(String[] args) throws Exception {
new Thread(new TalkSend(5555,"localhost",8888)).start();
new Thread(new TalkReceive(9999,"UP主")).start();
}
}

26890DC655E21EC1D241A2AFE697896D

FC48C1C0951408B970E6AE73C4E6AB34


1.12、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
package com.haibara.lesson04;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
* @projectName: study
* @package: com.haibara.lesson04
* @className: UrlDownload
* @author: Haibara
* @description: 访问互联网上的资源
*/
public class UrlDownload {
public static void main(String[] args) throws Exception{
//设置地址
URL url = new URL("https://m10.music.126.net/20211020154612/6e9398a4e832aeb692fd5a6a38d66c2a/ymusic/025c/0652/025c/56b3c6564118d2dbed38565d97627fd7.mp3");
//访问
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("从别后.mp3");
byte[] buffer = new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
fos.write(buffer,0,len);
}
fos.close();
inputStream.close();
//断开连接
urlConnection.disconnect();
}
}

访问互联网的内容保存到本地