【JavaEE】网络(2)
一、网络编程套接字
1.1 基础概念
【网络编程】指网络上的主机,通过不同的进程,以编程的方式实现网络通信;当然,我们只要满足进程不同就行,所以即便是同一个主机,只要是不同进程,基于网络来传输数据,也属于网络编程
【套接字】其实是socket的直译,套接字就是传输层给应用层提供的网络编程API(接口)通过这个接口,应用层程序可以通过这个接口使用传输层提供的服务,而不需要知道它的具体实现
套接字分为两类:流式套接字和数据报套接字
流式套接字是基于TCP协议(一个传输层协议)实现的,TCP是一种面向连接型、可靠传输型、面向字节流、全双工的传输层协议,流式套接字利用这些特性为应用层提供了一个简单的接口,用于发送和接收数据流
数据报套接字是基于UDP协议(也是一个传输层协议)实现的,UDP是一种面向无连接型、不可靠传输型、面向数据报、全双工的传输层协议
1.2 协议特点
接下来讲解以下上述提到的 TCP协议和UDP协议的特点
1)面向有连接型 vs 面向无连接型:通过网络发送数据分为面向有连接和面向无连接
有连接指在发送数据之前,发送端要先和接收端建立一条逻辑意义上的连接,连接建好后才能真正发送数据,数据发送完毕后要断开连接;
就好比打电话,在说话之前,对方要先同意接听,接听并说完话后再挂断电话
无连接则无需考虑建立连接和断开连接,发送端可以在任何时候发送数据,接收端不知道自己会在何时收到数据,所以要时常检查是否收到数据;
这个就像发送电子邮件,发送端可以随时发送,无需让接收端同意,接收端则要时常检查是否有收到邮件
2)可靠传输 vs 不可靠传输:
可靠传输指将要传输的数据尽可能的传输给对方,在网络通信的过程中,会存在"丢包"的情况:A给B传输10个数据报,B收到了9个;
原因是A传输给B,中间可能会经历很多交换机和路由器,这些交换机和路由器不只是转发你的数据,要转发很多数据,当数据很多时,可能会超过它们自身的硬件水平,此时多出来的数据无法转发,会被直接丢弃掉。
TCP为了对抗丢包,内部实现了一些机制(重发)来实现可靠传输(机制后面会详细讲)
不可靠传输指再出现丢包后,也不负责重发,不可靠传输更注重效率,在一些注重效率,对准确性要求不高的场景使用不可靠传输,可靠传输能尽可能保证数据传给接收端,但效率上会大打折扣
3)面向字节流 vs 面向数据报
面向字节流指传输的数据以字节为单位
面向数据报指传输的数据以数据报为单位,传输数据是一个一个数据报,一次读写只能读写完整的数据报,不能读写半个
4)全双工 vs 半双工
全双工指一条链路,能够进行双向通信,后续代码创建socket对象,既可以读(接收)也可以写(发送)
半双工指一条链路,只能进行单向通信
二、UDP-数据报套接字编程
socket API 是由传输层给应用层提供的API,传输层是封装于操作系统内核态的,由操作系统内核直接管理,所以可以理解为socket api是由操作系统内核管理的,而Java对于系统这些API进行了封装,所以使得用户程序可以直接使用这些API
UDP的socket API 有两个重要的类
2.1 DatagramSocket
属于UDP Socket,创建DatagramSocket的对象就可以发送和接收UDP数据报,先来看构造方法:
构造方法 | 描述 |
DatagramSocket( ) | 创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口 |
DatagramSocket( int port ) | 创建一个UDP数据报套接字的Socket,绑定到本机指定的端口号 |
普通方法:
普通方法 | 描述 |
void receive (DatagramPacket p) | 接收数据报,如果没有接收到,该方法就会阻塞等待 |
void send(DatagramPacket p) | 发送数据报,不会阻塞等待,直接发送(无连接) |
void close( ) | 关闭此数据报套接字 |
当创建一个套接字时,系统会为其分配资源绑定端口号,如果用完不关闭则会导致资源持续被占用
2.2 DatagramPacket
表示UDP Socket发送和接收的数据报,一个DatagramPacket对象就相当于一个UDP数据报
构造方法 | 描述 |
DatagramPacket (byte[] buf, int length) | 构造⼀个DatagramPacket以用来接收数据报,接收的数据保存在字节数组(第⼀个参数buf)中,接收指定长度(第⼆个参数length) |
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) | 构造⼀个DatagramPacket以用来发送数据报,发送的数据为字节数组(第⼀个参数buf)中,从0到指定⻓ 度(第⼆个参数length)address指定⽬的主机的IP 和端⼝号 |
上述方法可以结合下述代码理解
2.3 模拟回显服务器
回显服务器指客户端发送一个请求给服务端,服务端将这个请求原封不动的作为相应返回给客户端,这就叫回显(请求啥相应就是啥),接下来先编写服务器程序:
public class UdpEchoServer {public DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port); //创建 UDP Socket 并绑定一个端口号}}
服务器需要在程序启动的时候,把在服务器程序的端口号确定下来,客户端发送请求时需要知道服务器的IP地址(服务器所在主机的IP)、端口号port
服务器要能够接收客户端发送的数据,socket receive( );需要向receive传入一个UDP数据报
public class UdpEchoServer {public DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}public void start() throws IOException {//1) 接收请求DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);//此时创建好的requestPacket 是一个空的数据包//requestPacket包含两个部分1.报头 2.载荷//字节数组用来存储数据socket.receive(requestPacket); //客户端会send一个数据包, 就会跳转到这里//此时由requestPacket 是一个预留好空间的空数据包// 为了方便在 java 代码中处理 (尤其是后面进行打印) 可以把上述数据报中的二进制数据, 拿出来, 构造成 StringString request = new String(requestPacket.getData(), 0, requestPacket.getLength());}}
接收来自客户端的请求后,经过处理后将响应返回给客户端,那么该如何知道应该给哪个客户端返回响应,在我们receive接收到的数据包里就包含了这个数据包来自于哪个IP,来自于哪个端口号(客户端)
// 2) 根据请求计算响应
String response = this.process(request);
// 3) 把响应写回到客户端
DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), 0, response.getBytes().length, requestPacket.getSocketAddress());
socket.send(responsePacket);
requestPacket.getSocketAddress() 这个方法返回的对象里就包含了客户端的IP地址和端口号
上述代码干的事情就是将字符串类型的二进制数据再构造会UDP数据包并发送给客户端
服务端完整代码如下:
public class UdpEchoServer {private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}public void start() throws IOException {Scanner scanner = new Scanner(System.in);System.out.println("服务器启动!");while (true) { // 服务器需要7*24小时持续接收并处理请求// 1) 读取请求并解析DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);socket.receive(requestPacket);//receive方法中的requestPacket是一个空的数据包,客户端程序通过send方法发送有数据的数据包后//会直接跳转到这里的receive方法,而这里的requestPacket是一个预留好空间的空数据包// 为了方便在 java 代码中处理 (尤其是后面进行打印) 可以把上述数据报中的二进制数据, 拿出来, 构造成 StringString request = new String(requestPacket.getData(), 0, requestPacket.getLength());//将字节数组构造成String类的对象// 2) 根据请求计算响应String response = this.process(request);// 3) 把响应写回到客户端DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), 0, response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);System.out.printf("[%s:%d] req=%s, resp=%s\n", requestPacket.getAddress(), requestPacket.getPort(),request, response); // 从左到右依次为: IP地址,端口号,请求,响应}}// 由于当前写的是 "回显服务器"public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(9090);server.start();}
}
接下来写客户端代码:
首先客户端需要知道服务器的IP和端口号,端口号是我们之前就设置的9090,IP用127.0.0.1,当服务器和客户端在一个主机上,就用环回IP,这是系统提供的特殊的IP
public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;public UdpEchoClient(String serverIp, int serverPort) throws SocketException {socket = new DatagramSocket();// 这俩信息需要额外记录下来, 以备后续使用.this.serverIp = serverIp;this.serverPort = serverPort;}
}
上述构造socket对象没有指定端口号,这样操作系统会分配一个空闲的端口号,这个端口号每次重新启动程序都不一样
// 1. 从控制台读取用户输入
String request = scanner.next();
// 2. 构造请求并发送
// 构造请求数据报的时候, 不光要有数据, 还要有 "目标 "
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), 0, request.getBytes().length, InetAddress.getByName(serverIp), serverPort);
socket.send(requestPacket); //发送数据包
上述InetAddress.getByName(serverIp)是将字符串格式的IP地址转成Java能识别的InetAddress对象
发送完数据包,服务器经过处理返回响应,客户端就要接收响应
// 3. 读取响应数据
//构造一个空的数据包负责接收服务器返回的响应
DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);socket.receive(responsePacket);
// 4. 显示响应到控制台上.
String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
System.out.println(response);
在第2步执行完send后,客户端程序紧接着到第三步的receive,由于从发送请求到返回响应需要些时间,所以这里receive会阻塞,阻塞到接收到服务器返回响应
完整的客户端代码如下:
public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;public UdpEchoClient(String serverIp, int serverPort) throws SocketException {socket = new DatagramSocket();// 这俩信息需要额外记录下来, 以备后续使用.this.serverIp = serverIp;this.serverPort = serverPort;}public void start() throws IOException {System.out.println("客户端启动!");Scanner scanner = new Scanner(System.in);while (true) {System.out.print("请输入要发送的请求: ");// 1. 从控制台读取用户输入String request = scanner.next();// 2. 构造请求并发送// 构造请求数据报的时候, 不光要有数据, 还要有 "目标"DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), 0, request.getBytes().length,InetAddress.getByName(serverIp), serverPort);socket.send(requestPacket);// 3. 读取响应数据DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);socket.receive(responsePacket);// 4. 显示响应到控制台上.String response = new String(responsePacket.getData(), 0, responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);// UdpEchoClient client = new UdpEchoClient("139.155.74.81", 9090);client.start();}
}
接下来启动服务器程序和客户端程序:
客户端可以不断发送请求并得到响应
服务端会不断处理客户端的请求
相关文章:

【JavaEE】网络(2)
一、网络编程套接字 1.1 基础概念 【网络编程】指网络上的主机,通过不同的进程,以编程的方式实现网络通信;当然,我们只要满足进程不同就行,所以即便是同一个主机,只要是不同进程,基于网络来传…...

AI for Science 的完美实践——科研文献的智慧化提取获得“综述性文摘”的软件开发
实践是检验真理的唯一标准!show your codes! 1 综述性文摘的需求 再简单不过了。 甲方(综述性文摘)需求:针对项目特征或描述,从几百篇相关的科研论文(PDF)中智能提取相关内容,包括…...
前端使用xlsx.js实现 Excel 文件的导入与导出功能
前端使用xlsx.js实现 Excel 文件的导入与导出功能 在现代的 Web 开发中,处理文件上传和导出功能已经变得越来越常见,尤其是 Excel 文件的导入与导出。 我们将使用 Vue.js 和 XLSX.js 库来处理 Excel 文件的读取和生成。XLSX.js 是一个强大的 JavaScrip…...
React简单了解
原理简化了解 import React from "react" import { createRoot } form "react-dom/client"const element React.createElement(p,{id: hello},Hello World! )const container document.querySelector(#root) const root createRoot(container) root.r…...
backbone 和Run-Length Encoding (RLE)含义
在深度学习中,特别是在图像分割任务中,backbone(主干网络)是指用于特征提取的预训练神经网络模型。Backbone 的主要作用是从输入图像中提取有用的特征,这些特征随后会被用于更高层次的任务,如分类、检测或分…...

在Centos7上安装MySQL数据库 How to install MySQL on Centos 7
执行以下命令,下载并安装MySQL。 wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm && yum -y install mysql57-community-release-el7-10.noarch.rpm && yum install -y mysql-community-server --nogpgcheck执行以下…...
Linux docker-20.10.9安装
Linux Docker20.10.9安装 解压文件 tar -xvf docker-20.10.9.tgz 给docker执行文件赋予可执行权限 chmod 755 -R docker/复制docker到/usr/bin/目录下,使docker命令可以执行 cp docker/* /usr/bin/将Docker注册为service,创建docker.service文件 vim /etc/syst…...

操作系统(13)虚拟存储器
前言 操作系统中的虚拟存储器是一项关键技术,它为用户提供了一个远大于实际物理内存容量的逻辑内存空间。 一、定义与原理 虚拟存储器是具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的存储器系统。其逻辑容量由内存容量与外存容量之和决定&…...

《面向对象综合训练01~05》
《面向对象综合训练01~05》 训练01:文字版格斗游戏 第一步:创建游戏角色的javabean类 public class Role {private String name;private int blood;private char gender;private String face;//长相是随机的//创建男女长相的随机数组String[] boyfaces…...

电脑为什么会提示“msvcr120.dll缺失”?“找不到msvcr120.dll文件”要怎么解决?
电脑故障排查指南:揭秘“msvcr120.dll缺失”的真相与解决方案 在软件开发与日常维护的广阔天地里,遇到系统报错或文件缺失的情况可谓家常便饭。今天,我将带领大家深入探讨一个常见的系统提示——“msvcr120.dll缺失”,并揭秘其背…...

huggingface NLP-微调一个预训练模型
微调一个预训练模型 1 预处理数据 1.1 处理数据 1.1.1 fine-tune 使用tokenizer后的token 进行训练 batch tokenizer(sequences, paddingTrue, truncationTrue, return_tensors"pt")# This is new batch["labels"] torch.tensor([1, 1])optimizer A…...

【BUG记录】Apifox 参数传入 + 号变成空格的 BUG
文章目录 1. 问题描述2. 原因2.1 编码2.2 解码 3. 解决方法 1. 问题描述 之前写了一个接口,用 Apifox 请求,参数传入一个 86 的电话,结果到服务器 就变成空格了。 Java 接收请求的接口: 2. 原因 2.1 编码 进行 URL 请求的…...

Spring AI API 介绍
目录: Spring AI 框架介绍 Spring AI API 核心API简介 Spring AI 提供了很多便利的功能,主要如下: AI Model API “Model API” 提供了聊天、文本转图像、音频转录、文本转语音、嵌入等功能,且不局限于某个固定的大模型提供商…...

【MySQL】Linux使用C语言连接安装
📢博客主页:https://blog.csdn.net/2301_779549673 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! 📢本文由 JohnKi 原创,首发于 CSDN🙉 📢未来很长&#…...

2024年第十五届蓝桥杯青少组C++国赛—割点
割点 题目描述 一张棋盘由n行 m 列的网格矩阵组成,每个网格中最多放一颗棋子。当前棋盘上已有若干棋子。所有水平方向或竖直方向上相邻的棋子属于同一连通块。 现给定棋盘上所有棋子的位置,如果要使棋盘上出现两个及以上的棋子连通块,请问…...
【软件开发】做出技术决策
文章目录 专注于核心业务除非绝对必要,不要重写代码保持技术栈简单尽量减少依赖避免范围蔓延按照业务实际情况确定优先级在做出高风险决策前构建原型跨职能团队协作信任你的团队在过去的二十年里,我曾在多家初创企业担任软件开发人员、技术负责人以及首席技术官(包括创办自己…...

Airborne使用教程
1.安装环境 前提条件:系统已安装Ruby 打开终端输入如下命令 gem install airborne 或者在Gemfile添加 gem airborne 然后运行bundle install 2.编写脚本 在项目中新建api_tests_spec.rb文件 以GET接口"https://www.thunderclient.com/welcome"为…...

WPF实现曲线数据展示【案例:震动数据分析】
wpf实现曲线数据展示,函数曲线展示,实例:震动数据分析为例。 如上图所示,如果你想实现上图中的效果,请详细参考我的内容,创作不易,给个赞吧。 一共有两种方式来实现,一种是使用第三…...

EasyExcel 动态设置表格的背景颜色和排列
项目中使用EasyExcel把数据以excel格式导出,其中设置某一行、某一列单元格的背景颜色、排列方式十分常用,记录下来方便以后查阅。 1. 导入maven依赖: <dependency><groupId>com.alibaba</groupId><artifactId>easy…...
【 C++11 】类的新功能
C类的新功能 一、默认成员函数二、类成员变量初始化三、default关键字四、delete关键字六、final关键字七、override关键字 一、默认成员函数 八个默认成员函数 在C11之前,一个类中有如下六个默认成员函数: 构造函数。析构函数。拷贝构造函数。拷贝赋值…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...

Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...