网络架构
1825字约6分钟
2025-11-21
BS/CS架构优缺点

BS:服务器与Web端
CS:服务器与客户端
三要素

IP


本机地址

端口号

网络协议
七层网络协议


简化之后,变成四层网络协议
应用层、表示层、回话层合并成 应用层;数据链路层、物理层合并成 物理链路层

UDP协议与TCP协议
UDP协议:主要应用在数据要求不高的地方(在线视频,视频通话。。。)
TCP协议:主要应用在数据要求高的地方(文件下载,发送邮件。。。)

InetAddress类
public class IPnew01 {
public static void main(String[] args) throws UnknownHostException {
// 确定主机名以及IP地址
InetAddress byName = InetAddress.getByName("DESKTOP-13JEKRH");
System.out.println(byName); // DESKTOP-13JEKRH/192.168.1.133
// 返回主机名
String zhuji = byName.getHostName();
System.out.println(zhuji); // DESKTOP-13JEKRH
// 返回IP地址
String ip = byName.getHostAddress();
System.out.println(ip); // 192.168.1.133
}
}UDP通信协议核心类
发送原理:DatagramSocket通过对应端口发送数据,发送到对应IP地址对应的端口号(DatagramPacket中定义的)
DatagramSocket:指定端口
DatagramPacket:打包封装
发送端
public class UDP_Demo {
public static void main(String[] args) throws IOException {
// 括号内指定对应 发送端端口
// 有参:与对应端口号绑定
// 无参:随机端口号
DatagramSocket kd = new DatagramSocket();
// 打包
String str = "hello";
// 要将字符串转换成字符数组
byte[] by = str.getBytes();
// 接收端IP
InetAddress address = InetAddress.getByName("127.0.0.1");
// 接收端端口
int port = 8080;
// 数据 | 数据长度 | 接收端IP地址 | 接收端端口
DatagramPacket data = new DatagramPacket(by, by.length, address, port);
// 发送数据
kd.send(data);
// 释放资源
kd.close();
}
}接收端
public class UDP_js {
public static void main(String[] args) throws IOException {
// 接收端
// 端口为发送端指定的接收端口
DatagramSocket js = new DatagramSocket(8080);
// 接收
byte[] by = new byte[1024];
// 将数据存放在对应的数组中
DatagramPacket data = new DatagramPacket(by, by.length);
// 接收数据
js.receive(data);
// 解析
// 数据字符数组
byte[] sj = data.getData();
// 字符长度
int len = data.getLength();
// 发送端IP
InetAddress address = data.getAddress();
// 发送端端口
int port = data.getPort();
System.out.println("数据:" + new String(sj, 0, len));
System.out.println("IP: " + address + " 端口:" + port);
// 释放资源
js.close()
}
}聊天室
发送(每运行一个就是一个会话窗口)
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
DatagramSocket fs = new DatagramSocket();
while (true) {
System.out.print("说点吧~ :");
String str = scanner.next();
if (str.equals("exit")) {
break;
}
byte[] by = str.getBytes();
InetAddress ip = InetAddress.getByName("127.0.0.1");
int port = 8080;
DatagramPacket js = new DatagramPacket(by, by.length, ip, port);
fs.send(js);
}
}聊天界面(会话窗口发送的聊天信息会在这里显示)
public static void main(String[] args) throws IOException {
DatagramSocket js = new DatagramSocket(8080);
byte[] cc = new byte[1024];
DatagramPacket date = new DatagramPacket(cc, cc.length);
while (true) {
js.receive(date);
byte[] by = date.getData();
int len = date.getLength();
InetAddress ip = date.getAddress();
int port = date.getPort();
System.out.println(ip + ":" + port + ": " + new String(by, 0, len));
}
}组播
MulticastSocket是用于发送和接收 IP 多播数据包的类,它继承自DatagramSocket,专门用于处理多播(一对多通信)。多播允许一个发送者向多个接收者(加入同一多播组)发送数据,而无需单独向每个接收者发送,适用于流媒体、实时通信等场景
发送端
public static void main(String[] args) throws IOException {
MulticastSocket gb = new MulticastSocket();
String str = "组播测试";
byte[] by = str.getBytes();
int len = by.length;
// 向该组发送数据
InetAddress ip = InetAddress.getByName("224.0.0.1");
int port = 8888;
DatagramPacket data = new DatagramPacket(by, len, ip, port);
gb.send(data);
gb.close();
}接收端
public static void main(String[] args) throws IOException {
MulticastSocket js = new MulticastSocket(8888);
// 添加组
InetAddress address = InetAddress.getByName("224.0.0.1");
js.joinGroup(address);
byte[] by = new byte[1024];
DatagramPacket data = new DatagramPacket(by, by.length);
js.receive(data);
byte[] sj = data.getData();
int len = data.getLength();
InetAddress ip = data.getAddress();
int port = data.getPort();
System.out.println(ip + " " + port + ": " + new String(sj, 0, len));
}广播
public static void main(String[] args) throws IOException {
MulticastSocket gb = new MulticastSocket();
String str = "组播测试";
byte[] by = str.getBytes();
int len = by.length;
// 向所有组发送数据
InetAddress ip = InetAddress.getByName("255.255.255.255");
int port = 8888;
DatagramPacket data = new DatagramPacket(by, len, ip, port);
gb.send(data);
gb.close();
}TCP通信协议核心类
服务端
public static void main(String[] args) throws IOException {
// 服务端
// 接收端口
ServerSocket ser = new ServerSocket(6789);
// 监听客户端
// accept()是阻塞方法,程序会在这里停止,直到客户端连接过来
Socket acc = ser.accept();
// 获取输入流,接收客户端传过来的数据
InputStream is = acc.getInputStream();
// 转换流
InputStreamReader gbk = new InputStreamReader(is);
int a;
// 读取数据并输出
while ((a = gbk.read()) != -1) {
System.out.println((char) a);
}
// 释放资源
ser.close();
is.close();
}客户端
public static void main(String[] args) throws IOException {
// 连接服务器
Socket kh = new Socket("127.0.0.1", 6789);
// 获取输出流,向服务器发送数据
OutputStream os = kh.getOutputStream();
// 发送数据
os.write("你好".getBytes());
// 释放资源
os.close();
kh.close();
}TCP建立连接

TCP取消连接

接收与反馈
客户端
public static void main(String[] args) throws IOException {
// 客户端
Socket server = new Socket("127.0.0.1", 8080);
// 输出流
OutputStream out = server.getOutputStream();
String str = "你好";
out.write(str.getBytes());
// 关闭当前输出流,告知服务端 “后续不会再发送数据“
server.shutdownOutput();
// 输入流
InputStream js = server.getInputStream();
InputStreamReader zh = new InputStreamReader(js);
int num;
// 输出服务端发送过来的数据
while ((num = zh.read()) != -1) {
System.out.print((char) num);
}
server.close();
out.close();
}服务端
public static void main(String[] args) throws IOException {
// 服务端
ServerSocket server = new ServerSocket(8080);
// 监听
Socket jt = server.accept();
// 输入流
InputStream js = jt.getInputStream();
InputStreamReader zh = new InputStreamReader(js);
int b;
while ((b = zh.read()) != -1) {
System.out.print((char) b);
}
String str = "服务端接收成功";
// 输出流
OutputStream sc = jt.getOutputStream();
// 反馈给客户端
sc.write(str.getBytes());
jt.close();
server.close();
}发送文件
发送端
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 8889);
String filePath = "D:\\book\\11.png";
// 输出缓冲流,写数据 / 发送数据
BufferedOutputStream buOut =
new BufferedOutputStream(socket.getOutputStream());
// 输入缓冲流,读数据 / 接收数据
BufferedInputStream buInp =
new BufferedInputStream(new FileInputStream(filePath));
// OutputStream sc = socket.getOutputStream();
// FileInputStream file = new FileInputStream(filePath);
byte[] by = new byte[1024];
int len;
while ((len = buInp.read(by)) != -1) {
// 发送文件
buOut.write(by, 0, len);
}
// 强制刷新缓冲区,确保数据全部正常发送
buOut.flush();
socket.shutdownOutput();
// 将输入流转换成字符
BufferedReader buInp1 = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String line = buInp1.readLine();
System.out.println(line);
socket.close();
}服务端
public static void main(String[] args) throws IOException {
String name = UUID.randomUUID().toString().replace("-", "");
String filePath = "D:\\book\\" + name + ".png";
ServerSocket server = new ServerSocket(8889);
Socket jt = server.accept();
// 输入缓冲流,读数据 / 接收数据
BufferedInputStream buInp =
new BufferedInputStream(jt.getInputStream());
// 输出缓冲流,写数据 / 发送数据
BufferedOutputStream buOut =
new BufferedOutputStream(new FileOutputStream(filePath));
// InputStream js = jt.getInputStream();
// FileOutputStream xr = new FileOutputStream(filePath);
// 文件长度
int num;
byte[] by = new byte[1024];
while ((num = buInp.read(by)) != -1) {
// 写入接收的文件
buOut.write(by, 0, num);
}
// 强制刷新缓冲区,确保数据全部正常写入
buOut.flush();
// 将输出流转换成字节
BufferedWriter buOut1 = new BufferedWriter(
new OutputStreamWriter(jt.getOutputStream()));
// 发送反馈信息
buOut1.write("接收成功");
buOut1.close();
jt.close();
server.close();
}多线程接收文件
服务端
多个客服端同时发文件不会相互影响
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ser = new ServerSocket(8899);
// 自定义线程
ThreadPoolExecutor tpe = new ThreadPoolExecutor(
3,
6,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
while (true) {
Socket jt = ser.accept();
// new Thread(new Ser(jt)).start();
tpe.submit(new Ser(jt));
}
}
}
class Ser implements Runnable {
Socket jt;
public Ser(Socket jt) {
this.jt = jt;
}
public void run() {
String uuid = UUID.randomUUID().toString().replace("-", "");
String file = "D:\\book\\" + uuid + ".jpg";
try {
BufferedInputStream buInp = new BufferedInputStream(jt.getInputStream());
BufferedOutputStream buOut = new BufferedOutputStream(new FileOutputStream(file));
byte[] by = new byte[1024];
int len;
while ((len = buInp.read(by)) != -1) {
buOut.write(by, 0, len);
}
buOut.flush();
BufferedWriter buw = new BufferedWriter(new OutputStreamWriter(jt.getOutputStream()));
buw.write("接收成功!");
buw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (jt != null) {
try {
jt.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}