【网络】UDP回显服务器和客户端的构造,以及连接流程
回显服务器(Echo Server)
最简单的客户端服务器程序,不涉及到业务流程,只是对与 API 的用法做演示
客户端发送什么样的请求,服务器就返回什么样的响应,没有任何业务逻辑,没有进行任何计算或者处理
0. 构造方法
- 网络编程必须要使用网卡,就需要用到
Socket对象- 创建一个
DatagramSocket对象,之后在基于这个对象进行操作
- 创建一个
import java.net.DatagramSocket;
import java.net.SocketException; public class UdpEchoServer { private DatagramSocket socket = null; public UdpEchoServer(int port) throws SocketException { //SocketException 异常是 IOException 的子类socket = new DatagramSocket(port); }
}
- 对于服务器这一端来说,需要在
socket对象创建的时候,就指定一个端口号port,作为构造方法的参数 - 后续服务器开始运行之后,操作系统就会把端口号和该进程关联起来
- 端口号的作用就是来区分进程的,一台主机上可能有很多个进程很多个程序,都要去操作网络。当我们收到数据的时候,哪个进程来处理,就需要通过端口号去区分
- 所以就需要在程序一启动的时候,就把这个程序关联哪个端口指明清楚
- 在调用这个构造方法的过程中,
JVM就会调用系统的Socket API,完成“端口号-进程”之间的关联动作- 这样的操作也叫“绑定端口号”(系统原生
API名字就叫bind) - 绑定好了端口号之后,就明确了端口号和进程之间的关联关系
- 这样的操作也叫“绑定端口号”(系统原生
- 对于一个系统来说,同一时刻,一个端口号只能被一个进程绑定;但是一个进程可以绑定多个端口号(通过创建多个
Socket对象来完成)- 因为端口号是用来区分进程,收到数据之后,明确说这个数据要给谁,如果一个端口号对应到多个进程,那么就难以起到区分的效果
- 如果有多个进程,尝试绑定一个端口号,只有一个能绑定成功,后来的都会绑定失败
- 前面说到,这里的
socket对象也占用一个文件描述符表里面的资源,但在这个程序中却不需要进行文件关闭的操作- 因为此处代码中,
socket的生命周期是跟随整个进程的,当进程结束了,socket才需要关闭 - 此时,就算代码中没有
close,进程关闭,也就会释放文件描述附表里的所有内容,也就相当于close了
- 因为此处代码中,
1. 接收请求
- 通过
start来启动服务器的核心流程 - 对于服务器来说,主要的工作,就是不停地处理客户端发来的请求,因为客户端什么时候会发来请求是未知的,所以要时刻待命
public void start() { System.out.println("服务器启动!"); //通过一个死循环来不停地处理请求 while(true) { //1. 读取客户端的请求并解析socket.receive(); }
}
- 对
7*24小时工作的服务器来说,服务器里面有死循环是很正常的,不是说死循环就是代码bug
- 读取客户端的请求并解析
receive是从网卡上读取数据,但是调用receive的时候,网卡上不一定就有数据- 当调用
start方法之后程序启动,就立刻调用了receive,一调用receive,就会立刻从网卡中读取数据,但这个时候客户端可能还没来,网卡中还没有数据 - 如果网卡上收到数据了,
receive立刻返回,获取收到的数据;如果没有收到数据,receive就会阻塞等待,直到真正收到数据为止 - 此处
receive也是通过“输出型参数”获取到网卡上收到的数据的
receive的参数是DatagramPacket- 我们就需要构造一个空的
DatagramPacket对象,将其作为参数传递给receive
- 我们就需要构造一个空的
public void start() throws IOException { System.out.println("服务器启动!"); //通过一个死循环来不停地处理请求 while(true) { //1. 读取客户端的请求并解析 DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096); socket.receive(requestPacket); }
}
DatagramPacket自身需要存储数据,但是数据的空间具体多大,需要外部来定义,自身不负责- 需要指定
requestPacket所需要存储数据/持有数据的基数- 指定一个字节数组,和其长度
- 大小没什么讲究,只要能确保能够存储下你通讯的一个数据包即可
- 收到的请求数据是通过二进制
byte[]的形式来体现的,而我们后续要将其进行处理,最好将它转成字符串才好处理
public void start() throws IOException { System.out.println("服务器启动!"); //通过一个死循环来不停地处理请求 while(true) { //1. 读取客户端的请求并解析 DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096); socket.receive(requestPacket); //将收到的二进制 byte[] 数据转换成字符串 String request = new String(requestPacket.getData(),0,requestPacket.getLength()); }
}
- 构造
String可以基于字节数组构造,也可以基于字符数组进行构造- 此处
DatagramPacket里面持有的就是字节数组,我们就取出里面包含的字节数 - 此处就指定了:是哪个字节数组、从哪开始构造、构造多长
- 此处
2. 根据请求计算响应
- 请求(request):客户端主动给服务器发起的数据
- 响应(response):服务器给客户端返回的数据
此处是一个回显服务器,响应就是请求
public void start() throws IOException { System.out.println("服务器启动!"); //通过一个死循环来不停地处理请求 while(true) { //1. 读取客户端的请求并解析 DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096); socket.receive(requestPacket); //将收到的二进制 byte[] 数据转换成字符串 String request = new String(requestPacket.getData(),0,requestPacket.getLength()); //2. 根据请求计算响应 String response = process(request); }
} //请求是什么,响应就是什么
private String process(String request) { return request;
}
3. 将响应写回客户端
此时需要主动的将数据通过网卡发送回客户端
- 与
receive相似,send的参数是DatagramPacket- 我们就需要构造一个
DatagramPacket对象,将其作为参数传递给send - 但此时不能使用空的数组来构造
DatagramPacket对象 - 需要使用刚刚的
response数据进行构造
- 我们就需要构造一个
public void start() throws IOException { System.out.println("服务器启动!"); //通过一个死循环来不停地处理请求 while(true) { //1. 读取客户端的请求并解析 DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096); socket.receive(requestPacket); //将收到的二进制 byte[] 数据转换成字符串 String request = new String(requestPacket.getData(),0,requestPacket.getLength()); //2. 根据请求计算响应 String response = process(request); //3. 把响应写回到客户端 DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length, requestPacket.getSocketAddress()); socket.send(responsePacket); }
} //请求是什么,响应就是什么
private String process(String request) { return request;
}
String可以基于字节数组来构造,也可以随时取出里面的字节数组response.getBytes().length不能写成response.length- 前者是在获取字节数组,得到字节数组的长度,单位是“字节”
- 后者是在获取字符串中字符的个数,单位是“字符”
UDP有一个特点——无连接- 所谓的连接,就是通信双方保存对方的信息(IP+端口号)
- 就是说
DatagramSocket这个对象中,不持有对方(客户端)和 IP 端口的,进行send的时候,就需要在send的数据包里,把要“发给谁”这样的信息,写进去,才能够正确的把数据进行返回 - 所以要将信息也作为参数,传入
responsePacket中- 客户端刚才给服务器发了一个请求
requestPacket,这个包记录了这个数据是从哪来,从哪来就让它回哪去,所以直接获取这个requestPacket的信息就可以了 - 客户端的 IP 和端口就都包含在
requestPacket.getSocketAddress()中 - 后续往外发送数据包的时候,就知道该发去哪了

- 客户端刚才给服务器发了一个请求
- 相比之下,
TCP代码中,因为TCP是有连接的,则无需关心对端的 IP 和端口,只管发送数据即可
- 如果字符串里都是英文字母/阿拉伯数字/英文标点符号的话,都是
ASCII编码的,一个字符也就是一个字节这么长- 如果字符串里有中文,是
UTF8编码的,一个中文就是 3 个字节UTF8也是能兼容ASCII,当使用UTF8表示英文的时候,和ASCII表示英文是完全相同的
4. 完整代码
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException; public class UdpEchoServer { private DatagramSocket socket = null; public UdpEchoServer(int port) throws SocketException { socket = new DatagramSocket(port); } public void start() throws IOException { System.out.println("服务器启动!"); //通过一个死循环来不停地处理请求 while(true) { //1. 读取客户端的请求并解析 DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096); socket.receive(requestPacket); //将收到的二进制 byte[] 数据转换成字符串 String request = new String(requestPacket.getData(),0,requestPacket.getLength()); //2. 根据请求计算响应 String response = process(request); //3. 把响应写回到客户端 DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length, requestPacket.getSocketAddress()); socket.send(responsePacket); //4. 打印日志 System.out.printf("[%s:%d req=%s, res=%s\n",requestPacket.getAddress(),requestPacket.getPort(),request,response); } } //请求是什么,响应就是什么 private String process(String request) { return request; } public static void main(String[] args) throws IOException { UdpEchoServer server = new UdpEchoServer(9090); server.start(); }public static void main(String[] args) throws IOException { UdpEchoServer server = new UdpEchoServer(9090); server.start(); }
}
- 将端口号设为“9090”
客户端(Echo Client)
0. 构造方法
import java.net.DatagramSocket;
import java.net.SocketException; public class UdpEchoClient { 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的时候一定要指定端口号;- 服务器必须是指定了端口号,客户端主动发起的时候,才能找到服务器
- 客户端这边,创建
socket的时候最好不要指定端口号- 客户端是主动的一方,不需要服务器来找它,所以不需要指定端口号
- 不代表没有端口号,客户端这边的端口号是系统自动分配了一个端口
- 还有一个重要的原因,如果在客户端这里指定了端口之后,由于客户端是在用户的电脑上运行的,天知道用户的电脑上都有哪些程序,都已经占用了哪些端口了。万一你的代码指定的端口和用户电脑上运行的其他程序的端口冲突,就出
bug了- 让系统自动分配一个端口,就能确保是分配一个无人使用的空闲端口
- 创建出对象之后,需要明确好服务器在哪,才能发起请求
- 所以在构造方法中指定两个参数:
String serverIP(服务器 IP)、String serverPort(服务器端口) - 并将这两个内容通过成员变量记录下来,之后就可以进一步通过这两个成员指定这个 UDP 数据报具体发给谁
- 所以在构造方法中指定两个参数:
客户端分配端口不可取的原因:
- 比如你去下馆子,进到店里面之后,老板让你找个地方坐
- 你找个地方坐,必然是找个“空闲的地方”
- 并且你这次坐的地方大概率和以前来坐的地方是不同的(可能上次坐的地方有人了)
你给服务器分配了端口之后,就相当于说是:你每次去吃饭,都被固定坐那个位置,不管有人没人
1. 读取输入
- 从控制台读取到用户的输入
public void start() { System.out.println("启动客户端!"); Scanner scanner = new Scanner(System.in); while (true) { //1. 从控制台读取到用户的输入 System.out.println("-> "); String request = scanner.next(); }
}
2. 构造一个 UDP 请求
构造 UDP 请求,并发送给服务器
public void start() throws IOException { System.out.println("启动客户端!"); Scanner scanner = new Scanner(System.in); while (true) { //1. 从控制台读取到用户的输入 System.out.println("-> "); String request = scanner.next(); //2. 构造出一个 UDP 请求,发送给服务器 DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.length(),
InetAddress.getByName(this.serverIP),this.serverPort); socket.send(requestPacket);}
}
- 构造
requestPacket对象的时候,不是拿的空对象进行构造的,要拿request里面的 String 数组、数组长度、IP 和端口号进行构造- 此处是给服务器发送数据,发送数据的时候,UDP 数据报里就需要带有目标的
IP和端口号。接受数据的时候,构造的UDP数据报就是一个空的数据报
- 此处是给服务器发送数据,发送数据的时候,UDP 数据报里就需要带有目标的
- 因为计算机需要的
IP不是字符串的,而我们通过this.serverIP提供的是一个字符串IP,所以我们需要把这个IP转换成需要的类型再进行构造
构造对象时的注意事项:
DatagramPacket里面构造的字节数组,不能是空的数组,因为我们是要给服务器发东西,里面得有内容(从控制台读取的用户的输入),所以把刚才从控制台读取的request里面的字节数组取出来,然后构造到DatagramPacket里面- 还需要指定此数据报要发给哪个服务器,需要将这个服务器的
IP和端口号传进去- 这里传入
IP的时候,需要将IP类型转换成计算机需要的格式、
- 这里传入
3. 从服务器读取响应
public void start() throws IOException { System.out.println("启动客户端!"); Scanner scanner = new Scanner(System.in); while (true) { //1. 从控制台读取到用户的输入 System.out.println("-> "); String request = scanner.next(); //2. 构造出一个 UDP 请求,发送给服务器 DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.length(), InetAddress.getByName(this.serverIP),this.serverPort); socket.send(requestPacket); //3. 从服务器读取到响应 DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096); socket.receive(requestPacket); }
}
- 由于客户端给服务器发送请求之后,响应也不是立刻就会过来的,如果此时立刻去调用客户端,
receive也是可能会发生阻塞的
4. 完整代码
import java.io.IOException;
import java.net.*;
import java.util.Scanner; public class UdpEchoClient { 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) { //1. 从控制台读取到用户的输入 System.out.println("-> "); String request = scanner.next(); //2. 构造出一个 UDP 请求,发送给服务器 DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.length(), InetAddress.getByName(this.serverIP),this.serverPort); socket.send(requestPacket); //3. 从服务器读取到响应 DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096); socket.receive(requestPacket); //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); client.start(); }
}
- 此处传入的 IP 是一个特殊的 IP——环回 IP,这个 IP 就代表本机,如果客户端和服务器在同一个主机上,就使用这个 IP
- 将端口号设为“9090”,和上面的服务器一样,将服务器和客户端连接起来
服务器与客户端连接
将服务器和客户端运行起来之后,在客户端输入“hello”的请求之后:
- 客户端读取到“
hello”,构造出一个requestPacket数据报,发送给服务器 - 服务器收到之后,就会从
receive返回结果,再来转成String类型的request - 服务器继续执行
process - 服务器再构造出一个响应数据报
responsePacket - 服务器最后进行返回,并打印日志
- 客户端这边就会从
receive这里读到响应结果responsePacket - 最后客户端这边进行打印
//客户端
启动客户端!
-> hello
hello//服务器
[/127.0.0.1:65075 req=hello, res=hello
- 客户端:输入
hello之后,打印出hello - 服务器:输出
[/127.0.0. 1:65075 req=hello, res=hello- 此处的信息就是客户端给服务器发起请求,服务器处理的过程,关键日志
127.0.0.1是客户端 IP65075是客户端的端口号,客户端没有指定端口号,这是系统自动分配的空闲的端口号- 请求和响应都是
hello,因为是回显服务器,所以请求和响应是一样的
完整流程

此处的通信,是本机上的客户端和服务器通信,如果使用两个主机,能够跨主机通信吗?如果我把客户端代码发给你,你能通过你的客户端访问到我的这个服务器吗?
- 能,也不能
- 如果我就把服务器代码运行在我自己的电脑上,此时你是无法访问到我这个服务器的,除非你抱着你的电脑来我这,和我连上一样的 WiFi 才能访问(IPv 4 的锅)
- 如果把我写的服务器代码写到“云服务器”上,此时就是可以的。
- 云服务器拥有公网 IP,而我自己的电脑没有公网 IP
相关文章:
【网络】UDP回显服务器和客户端的构造,以及连接流程
回显服务器(Echo Server) 最简单的客户端服务器程序,不涉及到业务流程,只是对与 API 的用法做演示 客户端发送什么样的请求,服务器就返回什么样的响应,没有任何业务逻辑,没有进行任何计算或者…...
【智能流体力学】ANSYS Fluent工作流程设置、求解和后处理详解
目录 一、设置阶段1. **模型****功能** :**详细说明及原理** :2. **材料****功能** :**详细说明及原理** :3. **单元区域条件****功能** :**详细说明及原理** :4. **边界条件****功能** :**详细说明及原理** :5. **网格交界面****功能** :**详细说明及原理** :6. **动…...
最新UI六零导航系统源码 | 多模版全开源
六零导航页 (LyLme Spage) 致力于简洁高效无广告的上网导航和搜索入口,支持后台添加链接、自定义搜索引擎,沉淀最具价值链接,全站无商业推广,简约而不简单。 使用PHPMySql,增加后台管理 多模板选择,支持在…...
K8S中使用英伟达GPU —— 筑梦之路
前提条件 根据不同的操作系统,安装好显卡驱动,并能正常识别出来显卡,比如如下截图: GPU容器创建流程 containerd --> containerd-shim--> nvidia-container-runtime --> nvidia-container-runtime-hook --> libnvid…...
2024-2025年最值得选的Java计算机毕业设计选题大全:800个热门选题
一、前言 博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ…...
libnl教程(2):发送请求
文章目录 前言示例示例代码构造请求创建套接字发送请求 简化示例 前言 前置阅读要求:libnl教程(1):订阅内核的netlink广播通知 本文介绍,libnl如何向内核发送请求。这包含三个部分:构建请求;创建套接字;发送请求。 …...
【软件测试】功能测试理论基础
目录 项目的测试流程🏴 需求评审 评审形式 测试人员在需求评审中职责 测试计划与方案 测试计划 问题 测试方案🏴 测试计划与方案的对比 功能测试设计🏴 测试设计的步骤 项目的测试流程🏴 作用: 有序有效开展…...
玩机进阶教程-----回读 备份 导出分区来制作线刷包 回读分区的写入与否 修改xml脚本
很多工作室需要将修改好的系统导出来制作线刷包。前面分享过很多制作线刷包类的教程。那么一个机型中有很多分区。那些分区回读后要写入。那些分区不需要写入。强写有可能会导致不开机 不进系统的故障。首先要明白。就算机型全分区导出后在写回去 都不一定可以开机进系统。那么…...
MongoDB 插入文档
MongoDB 插入文档 MongoDB 是一个流行的 NoSQL 数据库,它使用文档存储数据。在 MongoDB 中,数据以 BSON(Binary JSON)格式存储,这是一种二进制表示的 JSON 格式。MongoDB 提供了灵活的数据模型,使得插入和查询文档变得非常简单。本文将详细介绍如何在 MongoDB 中插入文档…...
【内网】服务器升级nginx1.17.0
今天用rpm包升级内网nginx版本,上来就给我报错 警告:nginx-1.27.0-2.el7.ngx.x86_64.rpm: 头V4 RSA/SHA256 Signature, 密钥 ID 7bd9bf62: NOKEY 错误:依赖检测失败: libcrypto.so.10()(64bit) 被 nginx-1:1.27.0-2.el7.ngx.x…...
歌曲爬虫下载
本次编写一个程序要爬取歌曲音乐榜https://www.onenzb.com/ 里面歌曲。有帮到铁子的可以收藏和关注起来!!!废话不多说直接上代码。 1 必要的包 import requests from lxml import html,etree from bs4 import BeautifulSoup import re impo…...
transformer-explainer
安装和启动 找到这个项目,然后装好了。 这个项目的目的如名字。 https://github.com/poloclub/transformer-explainerTransformer Explained: Learn How LLM Transformer Models Work with Interactive Visualization - poloclub/transformer-explainerhttps:/…...
C#中的S7协议
S7协议-S7COMM S7COMM 进行写 CTOP->PDU type已知枚举值 0X0E连接请求0x0d连接确认0x08断开请求0x0c断开确认0x05拒绝访问0x01加急数据0x02加急数据确认0x04用户数据0x07TPDU错误0x0f数据传输 S7Header->ROSCTR已知枚举值 0X01JOB REQUEST。主站发送请求0x02Ack。从站…...
2024-08-16升级记录:使用Android RecyclerView控件显示列表型信息
在页面上使用RecyclerView实现一个列表型信息展示: 步骤如下: 一、在页面布局中添加RecyclerView控件 <TextViewandroid:id"id/txt_gnss_info"android:layout_width"match_parent"android:layout_height"wrap_content"…...
通义千问 ( 一 ) 基础实例
1.相关概念 1.1.模型与平台 1.1.1.通义千问 通义千问 : 是阿里云研发的大语言模型;用于理解和分析用户输入的自然语言,在不同领域和任务为用户提供服务和帮助。 具体应用场景如下: 文字创作:撰写故事、公文、邮件、剧本和诗歌…...
docker 修改数据目录
1.停止 Docker 服务 sudo systemctl stop docker sudo systemctl stop docker.socket2.复制数据目录 sudo cp -rp /var/lib/docker /data/ 或 # sudo rsync -aP /var/lib/docker/ /data/docker/3.修改 Docker 配置 编辑 Docker 的配置文件,设置新的数据目录&#…...
r4s软路由写入iStoreOS镜像
需要用到的工具: 1、r4s软路由 2、32G及以上的TF卡 3、TF卡读卡器 4、镜像写入软件(推荐Etcher,下载地址:https://github.com/balena-io/etcher/releases/download/v1.19.21/balenaEtcher-1.19.21.Setup.exe) 5、…...
[C++][opencv]基于opencv实现photoshop算法灰度化图像
测试环境】 vs2019 opencv4.8.0 【效果演示】 【核心实现代码】 BlackWhite.hpp #ifndef OPENCV2_PS_BLACKWHITE_HPP_ #define OPENCV2_PS_BLACKWHITE_HPP_#include "opencv2/core.hpp"namespace cv {class BlackWhite { public:float red; //红色的灰度系…...
Emacs23.x版本之重要特性及用法实例(一百五十六)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列…...
机器学习 第11章-特征选择与稀疏学习
机器学习 第11章-特征选择与稀疏学习 11.1 子集搜索与评价 我们将属性称为“特征”(feature),对当前学习任务有用的属性称为“相关特征”(relevant feature)、没什么用的属性称为“无关特征”(irrelevant feature)。从给定的特征集合中选择出相关特征子集的过程&a…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
