网络编程:计算机和计算机之间通过网络进行数据传输。网络编程三要素:ip、端口、协议。
1.常见的软件架构

image.png

image.png
2.ip
ip 是上网设备在网络中的地址,是唯一的。常见的ip分为IPv4、IPv6
IPv4
目前的主流方案,最多只有2^32次方个ip,目前已经用完了。
image.png
IPv6
为了解决IPv4不够用而出现的,最多有2^128次方个ip,可以为地球上每一粒沙子都设定ip
image.png
image.png
3.端口

image.png
4.协议

image.png
现在用的是 TCP/IP 参考模型

image.png

image.png
UDP协议和TCP协议的应用场景:
| 场景 | 推荐协议 | 原因 |
|---|---|---|
| 网页浏览、文件下载 | TCP | 需要可靠传输 |
| 实时视频/语音通话 | UDP | 低延迟比可靠性重要 |
| 金融交易、数据库 | TCP | 数据必须准确无误 |
| DNS 查询 | UDP | 快速响应,短连接 |
| 在线游戏(FPS) | UDP | 减少延迟,允许少量丢包 |
| IoT 传感器上报 | UDP | 高频小数据,可容忍丢包 |
5.InetAddress 类
InetAddress是Java网络编程中的一个核心类,用于表示IP地址(包括IPv4和IPv6地址)
主要用途
IP地址表示:封装IPv4或IPv6地址
域名解析:将主机名(域名)解析为IP地址
反向解析:将IP地址反向解析为主机名
本地地址获取:获取本机的IP地址
网络通信基础:作为Socket等网络类的基础
package com.网络编程;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class test {
public static void main(String[] args) throws UnknownHostException {
InetAddress adress = InetAddress.getByName("192.168.2.109");
System.out.println(adress);
String hostName = adress.getHostName();
System.out.println(hostName);
String ip = adress.getHostAddress();
System.out.println(ip);
}
}
// 打印输出:
/192.168.2.109
LAPTOP-1K0M6B4Q
192.168.2.109
6.UDP 通信程序的代码实现

image.png
(1)单播方式
单播是指一对一的通信方式,数据从一个发送方发送到一个接收方。
发送数据:

image.png
package com.网络编程;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDP_sendData {
public static void main(String[] args) throws IOException {
// 1.创建 DatagramSocket 对象(快递公司)
// 细节:
// 绑定端口,以后从这个端口往外发送数据
// 空参:所有可用的端口里随机找一个使用
// 有参:指定端口发送
DatagramSocket ds = new DatagramSocket();
// 2.打包数据
// 发送到哪个电脑的哪个端口上
InetAddress adress = InetAddress.getByName("127.0.0.1");
int port = 9000;
// 注意发送的数据是 byte 数组
byte[] data = "这是第一条数据。。。".getBytes();
DatagramPacket dataPackage = new DatagramPacket(data, data.length, adress, port);
// 3.发送数据
ds.send(dataPackage);
// 4.释放资源
ds.close();
}
}
接收数据:

image.png
package com.网络编程;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDP_receiveData {
public static void main(String[] args) throws IOException {
// 注意:需要先启动接收端再运行发送端
// 1.创建 DatagramSocket 对象(快递公司)
// 细节:
// 接收数据的时候需要传参 端口,要和发送的目标端口保持一致
DatagramSocket ds = new DatagramSocket(9000);
// 2.接收数据包
byte[] buf = new byte[1024]; // 接收1024个字节长度
DatagramPacket dp = new DatagramPacket(buf, buf.length);
// 注意:receive 方法是阻塞的,执行到这里会等发送端发送数据,没有接收到就一直等
ds.receive(dp);
// 3.解析数据包
byte[] data = dp.getData(); // 数据
int len = dp.getLength(); // 实际接收到了多少个字节,可能指定的这个 buf 长度大于实际发送过来的数据长度
String hostAddress = dp.getAddress().getHostAddress();
int port = dp.getPort();
System.out.println("接收到数据," + new String(data, 0, len));
System.out.println("数据是从" + hostAddress + "这台电脑的" + port + "端口发送的过来的");
// 4.释放资源
ds.close();
}
}
注意:需要先启动接收端再运行发送端才能看到效果
(2)组播方式
组播(多播)是指一对一组的通信方式,数据仅发送给加入特定组播组的主机。
发送端:

image.png
接收端:

image.png
(3) 广播方式
广播是指一对所有的通信方式,数据发送到同一局域网内的所有主机(广播域内的设备)。
广播方式只需要把单播的地址改为 255.255.255.255 即可

image.png
7.tcp通信的代码实现

image.png

image.png
发送端:
package com.网络编程;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class Tcp发送数据 {
public static void main(String[] args) throws IOException {
// 创建客户端的Socket对象
// 细节:创建对象时会连接服务器,如果连接不上,代码会报错
Socket s = new Socket("127.0.0.1", 9999);
// 获取输出流,写数据
OutputStream os = s.getOutputStream();
os.write("hello Tcp,来了来了".getBytes());
// 接收端的read方法不会停止,除非这个tcp链接关闭,或者手动结束输出流
//s.shutdownOutput();
// 释放资源
os.close();
s.close();
}
}
接收端:
package com.网络编程;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Tcp接收数据 {
public static void main(String[] args) throws IOException {
// 创建服务端的Socket对象
ServerSocket ss = new ServerSocket(9999);
// 监听客户端的连接
Socket s = ss.accept();
// 获取输入流,读数据,并把数据显示在控制它
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
int b;
while ((b = br.read()) != -1) {
System.out.print((char) b);
}
// 释放资源
s.close();
ss.close();
}
}

image.png

image.png
8.扩展
解决文件上传后重名的问题,可以使用 UUID 来生成一个唯一字符串

image.png
服务器文件上传(线程池)demo:
每接收到一个客户端的连接就开启一条线程,一个用户对应服务端一条线程。
image.png
接收流并存储到本地目录大致代码:
image.png
参考:黑马java教程




