IO系列(一) -一文带你读懂 java 中的IO流!
一、摘要
说到 IO,相信大家都不陌生,英文全称:Input/Output,即输入/输出,通常指数据在内部存储器和外部存储器或其他周边设备之间的输入和输出。
比如我们常用的SD卡、U盘、移动硬盘等等存储文件的硬件设备,当我们将其插入电脑的 usb 硬件接口时,我们就可以从电脑中读取设备中的信息或者写入信息,这个过程就涉及到 I/O 的操作。
当然,涉及 I/O 的操作,也不仅仅局限于硬件设备的读写,还有网络数据的传输。比如,我们在电脑上用浏览器搜索互联网上的信息,这个信息的过程也涉及到 I/O 的操作。
无论是从磁盘中读写文件,还是在网络中传输数据,可以说 I/O 主要为处理人机交互、机与机交互中获取和交换信息提供的一套解决方案。
在 Java 的 IO 体系中,类将近有 80 个,位于java.io
包下,初步看起来感觉非常复杂,但是经过一番梳理之后,你会发现还是有规律可循的。
从传输数据的格式角度看,可以大致分为两组:
- 基于字节操作的 I/O 接口:InputStream 和 OutputStream
- 基于字符操作的 I/O 接口:Reader 和 Writer
从传输数据的方式角度看,也可以大致分为两组:
- 基于磁盘操作的 I/O 接口:File
- 基于网络操作的 I/O 接口:Socket
虽然 Socket 类并不在java.io
包下,但是我们仍然把它们划分在一起,因为 I/O 的核心问题,要么是数据格式影响 I/O 操作,要么是传输方式影响 I/O 操作,也就是将什么样的数据写到什么地方的问题。
I/O 只是人与机器或者机器与机器交互的手段,除了在它们能够完成这个交互功能外,我们关注的就是如何提高它的运行效率,而数据格式和传输方式是影响效率最关键的因素。
下面我们基于这两点,来展开分析!
二、传输格式的分类
从传输格式角度看,可以分两类:字节流和字符流。
- 基于字节的输入和输出操作接口分别是:InputStream 和 OutputStream
- 基于字符的输入和输出操作接口分别是:Reader 和 Writer 。
2.1、字节流接口
字节流,是 I/O 流中最底层的流,能处理任何类型的数据传输,比如文字、图片、视频、文件等。
2.1.1、基于字节输入流的接口
打开 JDK 源码,整理之后,InputStream 输入流接口的类继承层次如下图所示:
这些输入流类,根据角色不同,还可以进行分类,分为:节点流和处理流。
- 节点流:指的是向指定的设备,比如磁盘、网络,进行读/写数据,也被称为底层流,直接和数据源相接
- 处理流:指的是在已存在的节点流或者处理流基础上,包装一些更加方便操作 io 流的功能,比如压缩、序列化、缓冲操作等,也被称为包装流
输入流类,根据角色的划分类别如下:
OutputStream 输出流的类层次结构也是类似。
2.1.2、基于字节输出流的接口
OutputStream 输入流接口的类继承层次如下图所示:
字节输出流类,根据角色的划分类别如下:
这里就不详细的介绍各个子类的使用方法,有兴趣的朋友可以查看 JDK 的 API 说明文档,笔者也会在后期的系列文章会进行详细的介绍。
这里只是重点想说一下,无论是输入还是输出,操作数据的方式可以组合使用,各个处理流的类并不是只操作固定的节点流,比如如下输出方式:
//将文件输出流包装到序列化输出流中,再将序列化输出流包装到缓冲中
OutputStream out = new BufferedOutputStream(new ObjectOutputStream(new FileOutputStream(new File("fileName")));
另外,输出流最终写到什么地方必须要指定,要么是写到硬盘中,要么是写到网络中,从图中可以发现,写网络实际上也是写文件,只不过写到网络中,需要经过底层操作系统将数据发送到其他指定的计算机中,而不是写入到本地硬盘中。
2.2、字符流接口
不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符,所以 I/O 操作的都是字节而不是字符。
那为什么要有操作字符的 I/O 接口呢?
这是因为我们的程序中通常操作的数据都是以字符形式,为了程序操作更方便而提供一个直接写字符的 I/O 接口,仅此而已!
除此之外,使用字节流操控文字时不是很方便,容易乱码,由此诞生了不同的字符集以及对应的字符编码规则!
由于全世界的文字博大精深,不同的字符集,占用的字节位数不同,以中文为例,在GBK
编码规则中,一个中文使用二个字节存储;而在UTF-8
编码规则中,一个中文使用三个字节存储,如果写入和读取的编码规则不一样,读取的字节数很容易裂开,导致出现乱码。
比如以下案例:
public static void main(String[] args) throws Exception {byte[] bytes = "学习Java语言".getBytes("ISO8859-1");File file = new File("encoding.txt");OutputStream out = new FileOutputStream(file);out.write(bytes);out.close();
}
文件的内容如下:
??Java??
为了更方便地处理中文这些字符,计算机就推出了字符编码规则。
实现原理:字节流 + 编码表。
- 当写入一段文字时,会使用指定的字符集,将该 String 编码为一系列字节,将结果存储到新的字节数组中,进行传输
- 当读取一段文字时,通过指定的字符集,解码指定的字节数组来构造新的 String,从而解决文字乱码的问题。
2.2.1、基于字符输入流的接口
Reader 输入流接口的类继承层次如下图所示:
同样的,字符输入流类,根据角色的划分类别如下:
2.2.2、基于字符输出流的接口
Writer 输出流的类继承层次如下图所示:
字符输出流类,根据角色的划分类别如下:
2.3、字节与字符的转化
刚刚我们说到,不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符,设计字符的原因是为了程序更方便的操作文本。
那么怎么将字符转化成字节或者将字节转化成字符呢?
其中,InputStreamReader
和OutputStreamWriter
就是转化桥梁。
2.3.1、输入流转换方案
输入流字符解码相关类结构的转化过程如下图所示:
从图上可以看到,InputStreamReader
类是字节到字符的转化桥梁,
其中StreamDecoder
指的是一个解码操作类,Charset
指的是字符集。
InputStream
到Reader
的过程需要指定编码字符集,否则将采用操作系统默认字符集,很可能会出现乱码问题,StreamDecoder
则是完成字节到字符的解码的实现类。
案例如下:
File file = new File("encoding.txt");
FileInputStream inputStream =new FileInputStream(file);
//字节输入流转为字符输入流
InputStreamReader streamReader =new InputStreamReader(inputStream, Charset.forName("UTF-8"));
2.3.2、输出流转换方案
输出流转化过程也是类似,如下图所示:
通过OutputStreamWriter
类完成字符到字节的编码过程,由StreamEncoder
完成编码过程。
案例如下:
File file = new File("output.txt");
FileOutputStream outputStream =new FileOutputStream(file);
//字符输出流转字节输出流
OutputStreamWriter streamWriter =new OutputStreamWriter(outputStream, Charset.forName("UTF-8"));
三、传输方式的分类
上文我们介绍了数据的传输格式,可以通过字节流和字符流接口来完成数据的传输,至于数据写到何处,主要取决于数据的传输方式。
从传输方式角度看,可以分两类:磁盘和网络。
- 基于磁盘操作的操作接口是:File
- 基于网络操作的操作接口是:Socket
3.1、文件接口
我们知道数据在磁盘的唯一最小描述就是文件,也就是说上层应用程序只能通过文件来操作磁盘上的数据,文件也是操作系统和磁盘驱动器交互的一个最小单元。
在 Java I/O 体系中,File
类是唯一代表磁盘文件本身的对象。
File 类定义了一些与平台无关的方法来操作文件,包括检查一个文件是否存在、创建、删除文件、重命名文件、判断文件的读写权限是否存在、设置和查询文件的最近修改时间等等操作。
值得注意的是 Java 中通常的 File 并不代表一个真实存在的文件对象,当你通过指定一个路径描述符时,它就会返回一个代表这个路径相关联的一个虚拟对象,这个可能是一个真实存在的文件或者是一个包含多个文件的目录。
例如,读取一个文件内容,程序如下:
public static void main(String[] args) throws Exception {StringBuilder str = new StringBuilder();char[] buf = new char[1024];// 读取文件的内容FileReader f = new FileReader("input.txt");while(f.read(buf)>0){str.append(buf);}str.toString();
}
以上面的程序为例,从硬盘中读取一段文本字符,操作流程如下图:
当我们传入一个指定的文件名来创建File
对象,通过FileReader
来读取文件内容时,会自动创建一个FileInputStream
对象来读取文件内容,也就是我们上文中所说的字节流来读取文件。
紧接着,会创建一个FileDescriptor
的对象,其实这个对象就是真正代表一个存在的文件对象的描述。
由于我们需要读取的是字符格式,所以需要StreamDecoder
类通过解码方法decode
,将字节转字符,至于如何从磁盘驱动器上读取一段数据,由操作系统帮我们完成。
3.2、网络接口
继续来说说数据传输的另一种处理方式:网络通信。
3.2.1、Socket 简介
在 Java 网络体系中,Socket
是描述计算机之间完成相互通信一种抽象定义。
光从描述看可能很难理解,打个比方,可以把Socket
比作为两个城市之间的交通工具,有了它,就可以在城市之间来回穿梭了;并且,交通工具有多种,每种交通工具也有相应的交通规则。
Socket 也一样,也有多种,大部分情况下我们使用的都是基于 TCP/IP 的流套接字,它是一种稳定的通信协议。
比较典型的基于 Socket 通信的应用程序场景,如下图:
主机 A 的应用程序要想和主机 B 的应用程序通信,必须通过 Socket 建立连接,而建立 Socket 连接必须需要底层 TCP/IP 协议来建立 TCP 连接。
3.2.2、建立通信链路
我们知道网络层使用的 IP 协议可以帮助我们根据 IP 地址来找到目标主机,但是一台主机上可能运行着多个应用程序,如何才能与指定的应用程序通信呢?
这个时候需要通过 TCP 或 UPD 协议,也就是指定对应的端口号。
通过 IP + 端口号,就可以创建一个代表唯一一个主机上的一个应用程序的通信链路了,创建后的通信链路我们称它为 Socket 实例。
以 TCP 协议为例,为了准确无误地把数据送达目标处,TCP 协议采用了三次握手策略,如下图:
其中,SYN 全称为 Synchronize Sequence Numbers,表示同步序列编号,是 TCP/IP 建立连接时使用的握手信号。
ACK 全称为 Acknowledge character,即确认字符,表示发来的数据已确认接收无误。
在客户机和客户机之间建立正常的 TCP 网络连接时,发送端首先发出一个 SYN 消息,接收端使用 SYN + ACK 应答表示接收到了这个消息,最后发送端再以 ACK 消息响应。
整体流程如下:
- 发送端 –(发送带有 SYN 标志的数据包 )–> 接受端(第一次握手);
- 接受端 –(发送带有 SYN + ACK 标志的数据包)–> 发送端(第二次握手);
- 发送端 –(发送带有 ACK 标志的数据包) –> 接受端(第三次握手);
完成三次握手之后,发送端和接收端之间建立起可靠的 TCP 连接,客户端应用程序与服务器应用程序就可以开始传送数据了。
3.2.3、传输数据
当客户端要与服务端通信时,客户端首先要创建一个 Socket 实例,也就是指定目标服务器的 IP 和端口。
默认操作系统将为这个 Socket 实例分配一个没有被使用的本地端口号,并创建一个包含本地、远程地址和端口号的套接字数据结构,这个数据结构将一直保存在系统中直到这个连接关闭。
- 客户端简单示例
public static void main(String[] args) throws IOException {//通过IP和端口与服务端建立连接Socket socket =new Socket("127.0.0.1",8080);//将字符流转化成字节流,并输出BufferedWriter bufferedWriter =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));String str="Hello,我是客户端!";bufferedWriter.write(str);bufferedWriter.flush();bufferedWriter.close();
}
- 服务端简单示例
public static void main(String[] args) throws Exception {//初始化服务端socket并且绑定 8080 端口ServerSocket serverSocket = new ServerSocket(8080);//循环监听所有连接的客户端请求while (true){try {//等待客户端的连接Socket socket = serverSocket.accept();//将字节流转化成字符流,读取客户端输入的内容BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream()));//读取一行数据String str = bufferedReader.readLine();//输出打印System.out.println("服务端收到客户端发送的信息:" + str);} catch (Exception e) {}}
}
我们先启动服务端程序,再运行客户端,服务端收到客户端发送的信息,打印结果如下:
服务端收到客户端发送的信息:Hello,我是客户端!
注意,客户端只有与服务端建立三次握手成功之后,才会发送数据,而 TCP/IP 握手过程,底层操作系统已经帮我们实现了!
当连接已经建立成功,服务端和客户端都会拥有一个Socket
实例,每个Socket
实例都有一个InputStream
和OutputStream
,正如我们前面所说的,网络 I/O 都是以字节流传输的,Socket
正是通过这两个对象来交换数据。
当Socket
对象创建时,操作系统同时将会为InputStream
和OutputStream
分别分配一定大小的缓冲区,数据的写入和读取都是通过这个缓存区完成的。
发送端将数据写到OutputStream
对应的SendQ
队列中,当队列填满时,数据将被发送到另一端InputStream
的RecvQ
队列中,如果这时RecvQ
已经满了,那么OutputStream
的write
方法将会阻塞直到RecvQ
队列有足够的空间容纳SendQ
发送的数据。
值得特别注意的是,缓存区的大小以及写入端的速度和读取端的速度非常影响这个连接的数据传输效率,由于可能会发生阻塞,所以网络 I/O 和磁盘 I/O 在数据的写入和读取还要有一个协调的过程,如果两边同时传送数据,可能会产生死锁的问题。
如何提高网络 IO 传输效率、保证数据传输的可靠,这个我们后面单独开篇进行讲解。
四、小结
本文阐述的内容较多,整合了很多有用的信息,从 Java 基本的 I/O 类库结构开始说起,主要介绍了 IO 的传输格式和传输方式,包括字节流和字符流接口相关的分类介绍,以及磁盘 I/O 和网络 I/O 的基本工作方式。
内容难免有所遗漏,和理解不到的位置,欢迎网友留言指出!
五、参考
1、https://developer.ibm.com/zh/articles/j-lo-javaio/
六、写到最后
最近无意间获得一份阿里大佬写的技术笔记,内容涵盖 Spring、Spring Boot/Cloud、Dubbo、JVM、集合、多线程、JPA、MyBatis、MySQL 等技术知识。需要的小伙伴可以点击如下链接获取,资源地址:技术资料笔记。
不会有人刷到这里还想白嫖吧?点赞对我真的非常重要!在线求赞。加个关注我会非常感激!
相关文章:

IO系列(一) -一文带你读懂 java 中的IO流!
一、摘要 说到 IO,相信大家都不陌生,英文全称:Input/Output,即输入/输出,通常指数据在内部存储器和外部存储器或其他周边设备之间的输入和输出。 比如我们常用的SD卡、U盘、移动硬盘等等存储文件的硬件设备ÿ…...
代码随想录算法训练营第六天| 242. 有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和
哈希表理论基础 [LeetCode] 242. 有效的字母异位词 [LeetCode] 242. 有效的字母异位词 文章解释 [LeetCode] 242. 有效的字母异位词 视频解释 题目: 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意:若 s 和 t 中每个字符出…...
【python】中的可迭代对象、迭代器、生成器
结论 凡是实现了__iter__() 方法的类都称之为可迭代对象,但 __iter__() 方法的返回值只能是迭代器和生成器for 循环的本质是先调用 __iter__() 方法,然后不断调用返回值的 __next__() 方法,直至报出异常 StopIteration,可迭代对象…...

短视频矩阵系统源码/saas--总后台端、商户端、代理端、源头开发
短视频矩阵系统源码/saas--总后台端、商户端、代理端、源头开发 搭建短视频矩阵系统源码的交付步骤可以概括为以下几个关键环节: 1. **系统需求分析**:明确系统需要支持的功能,如短视频的上传、存储、播放、分享、评论、点赞等。 2. **技术选…...

K8s:二进制安装k8s(单台master)
目录 一、安装k8s 1、拓扑图 2、系统初始化配置 2.1关闭防火墙selinx以及swap 2.2设置主机名 2.3在每台主机中添加hosts,做映射 2.4调整内核参数,将桥接的ipv4流量传递到iptables,关闭ipv6 2.4时间同步 3、部署docker引擎࿰…...

C++类和对象下——实现日期类
前言 在学习了类和对象的六大成员函数后,为了巩固我们学习的知识可以手写一个日期类来帮助我们理解类和对象,加深对于其的了解。 默认函数 构造函数 既然是写类和对象,我们首先就要定义一个类,然后根据实际需要来加入类的数据与函…...

252 基于MATLAB的自适应差分阈值法检测心电信号的QRS波
基于MATLAB的自适应差分阈值法检测心电信号的QRS波,QRS波群反映左、右心室除极电位和时间的变化,第一个向下的波为Q波,向上的波为R波,接着向下的波是S波。通过GUI进行数据处理,展示心率和QRS。程序已调通,可…...

SSIM(Structural Similarity),结构相似性及MATLAB实现
参考文献 Wang, Zhou; Bovik, A.C.; Sheikh, H.R.; Simoncelli, E.P. (2004-04-01). “Image quality assessment: from error visibility to structural similarity”. IEEE Transactions on Image Processing. 13 (4): 600–612. Bibcode:2004ITIP…13…600W. CiteSeerX 10.…...
第十六章-消费者-PUSH方式(一)
16.1 准备阶段 先从一段官方示例代码开始 public class Consumer {public static void main(String[] args) throws InterruptedException, MQClientException {// 初始化consumer,并设置consumer group nameDefaultMQPushConsumer consumer new DefaultMQPushCo…...

【C++要哮着学】初识C++,什么是C++?什么是命名空间?什么又是缺省函数?
文章目录 前言1、C简介1.1、什么是C1.2、C起源1.3、C发展 2、C关键字(C98)3、命名空间3.1、命名空间的定义及使用3.2、命名空间的嵌套3.3、命名空间的三种使用方式3.3.1、加命名空间名称及作用域限定符3.3.2、使用using将命名空间中某个成员引入3.3.3、使…...
Lua 数字格式化
在编程中,对数字进行格式化是一项常见的任务,特别是当我们需要在用户界面中显示数据或生成报告时。在 Lua 中,我们可以使用一些简单而有效的函数来实现数字的格式化。在本文中,我们将介绍一个由几个函数组成的小型 Lua 库…...

Java入门基础学习笔记13——数据类型
数据类型的分类: 基本数据类型 引用数据类型 基本数据类型:4大类8种类型: 定义整形用int,再大的数用long。 package cn.ensource.variable;public class VariableDemo2 {public static void main(String[] args) {//目标&#x…...

使用Docker+Jar方式部署微服务工程(前后端分离)看着一篇就够了
本篇教程的使用到的技术有springboot、springcloud、Nacos、Docker、Nginx部署前后端分离访问的微服务。 部署一下Nacos 首先我们需要在服务器中(或者本地部署启动一下Nacos),这里我采用服务器的方式进行部署,这里有一点不一样的…...

红外遥控和LCD1602
26.1.1 红外线简介 人的眼睛能看到的可见光按波长从长到短排列,依次为红、橙、黄、绿、青、蓝、紫。其中红光的波长范围为 0.62~0.76μm;紫光的波长范围为 0.38~0.46μm。比紫光波长还短的光叫紫外线,比红光波长还长的…...

房屋出租管理系统需求分析及功能介绍
房屋租赁管理系统适用于写字楼、办公楼、厂区、园区、商城、公寓等商办商业不动产的租赁管理及租赁营销;提供资产管理,合同管理,租赁管理, 物业管理,门禁管理等一体化的运营管理平台,提高项目方管理运营效率…...
高精度模拟算法
高精度模拟算法 高精度加法 extern string m,n; extern int a[MAX],b[MAX],ans[MAX]; void addition(){int _mmax(m.size(),n.size());reverse(m.begin(),m.end()),reverse(n.begin(),n.end());//转置原字符串for(int i0;i<m.size();i) a[i]m[i]-0;//字符型以ASCII码存储&…...

Ansible简介版
目录 架构 环境部署 一、Ansible安装部署 1.yum安装Ansible 2.修改主机清单文件 3.配置密钥对验证 4.ansible-doc 5.看被控主机 二、常用模块 1.Command模块 2.Shell模块 3.Cron模块 1.添加 2.删除 4.User模块 5.Group模块 1.创建组 编辑 编辑 编辑…...

卷积通用模型的剪枝、蒸馏---蒸馏篇--RKD关系蒸馏(以deeplabv3+为例)
本文使用RKD实现对deeplabv3+模型的蒸馏;与上一篇KD蒸馏的方法有所不同,RKD是对展平层的特征做蒸馏,蒸馏的loss分为二阶的距离损失Distance-wise Loss和三阶的角度损失Angle-wise Loss。 完整代码放在文末。 一、RKD简介 RKD算法的核心是以教师模型的多个输出为结构单元,取…...

AVL树的完全指南:平衡与性能
文章目录 AVL树简介AVL的操作建立一个AVL树插入操作删除操作 书写代码1.构造函数和析构函数2.获取最大值和最小值3.树的高度和节点个数3.前序中序和后序遍历4.判断树是否为空树5.四个旋转操作6.获取平衡因子7.插入操作8.删除操作9.搜索节点.h文件中的定义 总结 AVL树简介 AVL树…...
itext7 PDF添加水印,获取页面高度,添加到页面右上角
ps: pdf添加水印,内容多的时候会往下跑,修改为获取当前页面高度,进行固定在顶部,其他需要可以自己进行调整,直接贴代码。 public static void main(String[] args) throws IOException {String localFilePath "…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...

【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
加密通信 + 行为分析:运营商行业安全防御体系重构
在数字经济蓬勃发展的时代,运营商作为信息通信网络的核心枢纽,承载着海量用户数据与关键业务传输,其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级,传统安全防护体系逐渐暴露出局限性&a…...