当前位置: 首页 > news >正文

【Linux】 UDP网络套接字编程

🍎作者:阿润菜菜
📖专栏:Linux系统网络编程


文章目录

  • 一、网络通信的本质(port标识的进程间通信)
  • 二、传输层协议UDP/TCP
    • 认识传输层协议UDP/TCP
    • 网络字节序问题(规定大端)
  • 三、socket编程API和sockadder结构
    • 深入理解socket函数
    • socket常见API
    • sockaddr结构
  • 四、动手实现简单的UDP网络程序


一、网络通信的本质(port标识的进程间通信)

在网络基础部分,我们学习了什么是ip地址。
1.只要有目的ip地址和源IP地址就能够完成客户端和服务器的通信了吗
并不是这样的,实际通信的并不是两台主机,而是两台主机上分别的客户端进程和服务器进程,ip地址能够标识主机的全网唯一性,那用什么来标识客户端进程和服务器进程的唯一性呢?其实是用端口号port来标识的。2.所以只要有ip地址+port就能够确定数据包发送给哪一个主机的哪一个进程了
其中端口号是传输层协议的内容,应用层可以通过system call来获取端口号,端口号是一个2字节16位的整数,最大可达到65536的大小,因为传输层和网络层是操作系统实现的,所以port可以告诉操作系统应该将数据包发送给目标主机的哪一个进程。端口号在同一个ip地址对应的主机内只能被一个进程所占用,所以不同主机内部可能会出现相同端口号,这是很正常的事情,因为port标识的进程唯一性是在一台主机内部的,不同主机内出现相同port是很正常的。
例如下面图中主机A和主机B分别通过自己的ip+port标定了各自内部的进程在全网中的唯一性,从而实现跨局域网的网路通信。
在这里插入图片描述
3.所以网络通信的本质实际就是进程间通信,只不过今天的进程间通信是跨主机,跨网络的,而之前我们学习的进程间通信只是在一台主机内部各自进程之间的通信,并没有跨主机和跨网路,而在ip和port以及网络协议栈的支撑下,就能够实现跨主机跨网络的进程间通信,而这样的进程间通信实际就是网络通信
如果要来谈进程间通信的话,我们说过进程间通信的前提是让不同的进程先看到同一份资源,这份资源是什么呢?这份资源其实就是网络,包括局域网和广域网。而通信的本质实际就是IO,我们所有的上网行为无外乎就是两种,一种是将自己的数据发送出去,一种是接收别人给我发的数据


4.那么问题来了 – 既然进程已经有pid了,为什么还要有port来标识唯一的进程呢?
理由1:系统是系统,网络是网络,我们并不希望这两个模块儿是强耦合在一起的,因为一旦强耦合一个改变时另一个也需要改动,代码的鲁棒性不好,单纯从技术角度来讲,只用pid不用port绝对是可以实现的,但我们希望系统和网络能够解耦,互不影响。
理由2:服务器进程的端口号是不能轻易改变的,一个服务器设置好端口号之后,很长一段时间内这个服务器会一直使用这个端口号,因为客户端需要每次快速准确的找到服务器进程,所以这就意味着服务器的ip和port都是不能轻易改动的,就像110,120,119的电话一样,一旦设置了能轻易改动吗?当然是不能轻易改动的!而进程的pid是每次操作系统给随机分配的,每次的pid都是随机的,所以需要有port来标识进程。
理由3:不是所有的进程都需要提供网络服务,但所有的进程都需要有pid。

5.所以当进程绑定一个端口号之后,我们便称这个进程为网络服务进程
那底层操作系统如何依靠这个uint16_t类型的端口号找到对应的进程结构体struct task_struct结构体呢?这里简单说一下,底层中操作系统实际是通过哈希的方案通过port来找到对应的PCB结构体的,用端口号作为哈希表的key值,哈希桶中存放对应的PCB结构体地址,也就是struct task_struct类型的指针,只要找到PCB指针,那就能找到进程相关的所有信息,例如文件描述符表struct files_struct *files,进程的信号位图,地址空间等等一系列信息

6.另外,一个进程可以绑定多个端口号,但一个端口号不能被多个进程绑定。
比如某个端口号代表的服务器进程功能是传数据的,另外的端口号是执行指令的,那么有可能一个服务器进程兼具了这两种功能,当客户端向这两个端口号发送数据进行请求时,有可能请求到的是同一个服务器进程,这个服务器进程同时响应两个客户端的请求,为他们同时提供服务。
但一个端口号只能对应一个进程,否则客户端向该端口号发送请求的时候,进行响应的都不知道是哪个进程了,此时就有可能出现服务器接收数据丢失或失败等问题。
在有些网络服务中,可能会出现留后门的情况,即为一个进程绑定了两个端口号,一个端口号给客户用,一个端口号给另外的某个人用,但客户并不知晓,这就是软件开后门 — 就比如说我们之前四六级报名时有时候换个网站速度就会更快些。

二、传输层协议UDP/TCP

认识传输层协议UDP/TCP

TCP/UDP都是传输层协议,我们在进行网络编程时,一定是少不开访问传输层的,因为应用层在进行开发时,一定会调用传输层和应用层之间的system call API。

TCP叫做传输控制协议,他在进行网络通信时,是需要建立连接的,所以TCP是一种可靠传输,当然我们是无法感受到这种可靠性的,因为传输层在OS中,我们只停留在应用层。另外TCP是面向字节流的。

UDP叫做用户数据报协议,他在进行网络通信时,不需要建立连接,所以UDP是一种不可靠传输,同样我们还是无法感受到这种不可靠性。UDP是面向数据报的。

等到后面进行套接字编程的时候你就能体会到了,UDP在通信时,客户端发什么服务器就接受什么,通信起来非常的方便,TCP在通信时就比较繁琐,需要先建立链接,然后用文件IO(字节流)那一套来进行客户端和服务器的通信.
但需要注意的是可靠和不可靠都是中性词,并不是说不可靠是贬义词,针对不同的常见适合不同的传输层协议,例如银行转账时一定是要用TCP协议的,数据的传输必须是稳定可靠的,但某些网络广告推送就比较适合用UDP,因为稳定可靠一定是有代价的,在代码处理上一定是更为繁琐复杂的,维护和编码的成本一定是比较高的。而广告推送这样的场景对稳定可靠的要求没那么高,自然就比较适合使用UDP协议,因为维护和编码的成本低。

在这里插入图片描述

网络字节序问题(规定大端)

网络中传输的数据规定是大端的
协议谈完之后,需要面临的第一个问题就是网络字节序的问题,因为我们知道一般企业级的服务器一般都是大端字节序,我们用户级的笔记本都是小端,不同的主机使用的大小端都是不同的,这该怎么统一 一下呢?如果某个主机发送的数据是小端字节序,而接收的主机按照大端字节序来进行数据解释,这一定是会出问题的。
所以早在网络还没有大面积推广的时候,就已经规定了网络中的数据必须是大端的,如果你是小端机那就必须先将数据转为大端然后再发送到网络中,如果是大端机则直接发送数据即可。
其实这样规定也是有一定道理的,因为小端规定数据的高位在高地址处,低位在低地址处,而地址是从左向右逐渐增大的,数据的比特位是从左向右逐渐减小的,则内存中的存放和逻辑上的形式正好是反过来的,不利于看待,大端字节序更符合我们的逻辑认知。
主机在发送数据和接收数据时,都是按照从低地址到高地址的顺序来进行发送和接收。
在这里插入图片描述
小端和大端之间的转换工作谁来做呢?
Linux早已为我们提供好了一批字节序的转换API了==。主机和网络分别对应host和net,l和s代表long和short,主机转网络时,会统一将数据转换为大端,网络转主机时,会将数据转换成主机的字节序,可能是大端也可能是小端,这取决于主机的字节序==。
上面接口只提供了short和long两种数据类型,那如果有char和double的数据类型要进行主机和网络的转换呢?一般在网络发送的时候发送的数据都是字符串,如果能显示用上面的接口那就显示用,如果类型不匹配,那就发送隐式类型转换,系统帮我们做这个工作。

在这里插入图片描述

三、socket编程API和sockadder结构

socket编程是一种基于网络协议的通信机制,可以让不同主机上的进程进行双向通信。

深入理解socket函数

先来具体看一下socket函数用法
创建套接字的函数叫做socket,该函数的函数原型如下:

int socket(int domain, int type, int protocol); 

参数说明:

  • domain:创建套接字的域或者叫做协议家族,也就是创建套接字的类型。该参数就相当于struct sockaddr结构(下面有讲解)的前16个位。如果是本地通信就设置为AF_UNIX,如果是网络通信就设置为AF_INET(IPv4)或AF_INET6(IPv6)。
  • type:创建套接字时所需的服务类型。其中最常见的服务类型是SOCK_STREAMSOCK_DGRAM,如果是基于UDP的网络通信,我们采用的就是SOCK_DGRAM,叫做用户数据报服务,如果是基于TCP的网络通信,我们采用的就是SOCK_STREAM,叫做流式套接字,提供的是流式服务。
  • protocol:创建套接字的协议类别。你可以指明为TCP或UDP,但该字段一般直接设置为0就可以了,设置为0表示的就是默认,此时会根据传入的前两个参数自动推导出你最终需要使用的是哪种协议。

返回值说明:

  • 套接字创建成功返回一个文件描述符,创建失败返回-1,同时错误码会被设置。
  1. socket函数属于什么类型的接口?
    网络协议栈是分层的,按照TCP/IP四层模型来说,自顶向下依次是应用层、传输层、网络层和数据链路层。而我们现在所写的代码都叫做用户级代码,也就是说我们是在应用层编写代码,因此我们调用的实际是下三层的接口,而传输层和网络层都是在操作系统内完成的,也就意味着我们在应用层调用的接口都叫做系统调用接口
    2.socket函数是被谁调用的?
    socket这个函数是被程序调用的,但并不是被程序在编码上直接调用的,而是程序编码形成的可执行程序运行起来变成进程,当这个进程被CPU调度执行到socket函数时,然后才会执行创建套接字的代码,也就是说socket函数是被进程所调用的。
    3.socket函数底层做了什么?
    socket函数是被进程所调用的,而每一个进程在系统层面上都有一个进程地址空间PCB(task_struct)、文件描述符表(files_struct)以及对应打开的各种文件。而文件描述符表里面包含了一个数组fd_array,其中数组中的0、1、2下标依次对应的就是标准输入、标准输出以及标准错误。
    在这里插入图片描述
    当我们调用socket函数创建套接字时,实际相当于我们打开了一个“网络文件,打开后在内核层面上就形成了一个对应的struct file结构体,同时该结构体被连入到了该进程对应的文件双链表,并将该结构体的首地址填入到了fd_array数组当中下标为3的位置,此时fd_array数组中下标为3的指针就指向了这个打开的“网络文件”,最后3号文件描述符作为socket函数的返回值返回给了用户
    在这里插入图片描述
    其中每一个struct file结构体中包含的就是对应打开文件各种信息,比如文件的属性信息、操作方法以及文件缓冲区等。其中文件对应的属性在内核当中是由struct inode结构体来维护的,而文件对应的操作方法实际就是一堆的函数指针(比如read*和write*)在内核当中就是由struct file_operations结构体来维护的。而文件缓冲区对于打开的普通文件来说对应的一般是磁盘,但对于现在打开的“网络文件”来说,这里的文件缓冲区对应的就是网卡。
    在这里插入图片描述
    对于一般的普通文件来说,当用户通过文件描述符将数据写到文件缓冲区,然后再把数据刷到磁盘上就完成了数据的写入操作。而对于现在socket函数打开的“网络文件”来说,当用户将数据写到文件缓冲区后,操作系统会定期将数据刷到网卡里面,而网卡则是负责数据发送的,因此数据最终就发送到了网络当中。

socket常见API

以下是socket编程常见的几个API,现在混个眼熟就行,后面我们会进行代码的编写,到时候就知道怎么用这些API了

socket编程有两种主要的类型:TCP和UDP

TCP是一种面向连接的、可靠的、面向字节流的协议,适合于传输大量数据或需要保证数据完整性的场景。TCP的常用API有:

  • socket: 创建一个套接字,指定协议族、套接字类型和协议类型。
  • bind: 将一个套接字绑定到一个地址上,指定套接字、地址结构和地址长度。
  • listen: 监听一个套接字上的连接请求,指定套接字和队列长度。
  • accept: 接受一个连接请求,返回一个新的套接字和客户端地址。
  • connect: 发起一个连接请求,指定套接字、服务器地址和地址长度。
  • read/write: 从套接字读写数据,指定套接字、缓冲区和数据长度。
  • close: 关闭一个套接字,释放资源。

UDP是一种无连接的、不可靠的、面向数据报的协议,适合于传输少量数据或需要实时性的场景。UDP的常用API有:

  • socket: 创建一个套接字,指定协议族、套接字类型和协议类型。
  • bind: 将一个套接字绑定到一个地址上,指定套接字、地址结构和地址长度。
  • sendto/recvfrom: 向指定地址发送或从指定地址接收数据报,指定套接字、缓冲区、数据长度、标志位和地址结构。
  • close: 关闭一个套接字,释放资源。

sockaddr结构

套接字不仅支持跨网络的进程间通信,还支持本地的进程间通信(域间套接字)。在进行跨网络通信时我们需要传递的端口号和IP地址,而本地通信则不需要,因此套接字提供了sockaddr_in结构体和sockaddr_un结构体,其中sockaddr_in结构体是用于跨网络通信的,而sockaddr_un结构体是用于本地通信的。

为了让套接字的网络通信和本地通信能够使用同一套函数接口,于是就出现了sockeaddr结构体,该结构体与sockaddr_in和sockaddr_un的结构都不相同,但这三个结构体头部的16个比特位都是一样的,这个字段叫做协议家族
在这里插入图片描述

注意实际我们在进行网络通信写代码时,定义的还是sockaddr_in这样的结构体,只不过在传参时需要将该结构体的地址类型进行强转为sockaddr*罢了
1.为什么要定义这么多本地进程间通信的方式?

本地进程间通信的方式已经有管道、消息队列、共享内存、信号量等方式了,现在在套接字这里又出现了可以用于本地进程间通信的域间套接字,为什么会有这么多通信方式,并且这些通信方式好像并不相关?

实际是因为早期有很多不同的实验室都在研究通信的方式,由于是不同的实验室,因此就出现了很多不同的通信方式,比如常见的有System V标准的通信方式和POSIX标准的通信方式

  • IPv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包括16位地址类型,16位端口号和32位IP地址。
  • IPv4、IPv6地址类型分别定义为常数AF_INET、AF_INET6。这样,只要取得某种sockaddr结构体的首地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容。
  • socket API可以都用struct sockaddr* 类型表示,在使用的时候需要强制转化成sockaddr_in这样的好处是程序的通用性,可以接收IPv4、IPv6,以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数

2.为什么没有用void代替struct sockaddr类型?
我们可以将这些函数的struct sockaddr参数类型改为void,此时在函数内部也可以直接指定提取头部的16个比特位进行识别,最终也能够判断是需要进行网络通信还是本地通信,那为什么还要设计出sockaddr这样的结构呢?

实际在设计这一套网络接口的时候C语言还不支持void*,于是就设计出了sockaddr这样的解决方案。并且在C语言支持了void*之后也没有将它改回来,因为这些接口是系统接口,系统接口是所有上层软件接口的基石,系统接口是不能轻易更改的,否则引发的后果是不可想的,这也就是为什么现在依旧保留sockaddr结构的原因。

四、动手实现简单的UDP网络程序

详见代码仓库:udp实现回声服务器

相关文章:

【Linux】 UDP网络套接字编程

🍎作者:阿润菜菜 📖专栏:Linux系统网络编程 文章目录 一、网络通信的本质(port标识的进程间通信)二、传输层协议UDP/TCP认识传输层协议UDP/TCP网络字节序问题(规定大端) 三、socket编…...

《golang设计模式》第一部分·创建型模式-05-工厂方法模式(Factory Method)

文章目录 1 概述2.1 角色2.2 类图 2 代码示例2. 1 设计2.2 代码2.3 类图 3. 简单工厂3.1 角色3.2 类图3.3 代码示例3.3.1 设计3.3.2 代码3.3.3 类图 1 概述 工厂方法类定义产品对象创建接口,但由子类实现具体产品对象的创建。 2.1 角色 Product(抽象产…...

Kubernetes 概述

1、K8S 是什么? K8S 的全称为 Kubernetes (K12345678S) 作用 用于自动部署、扩展和管理“容器化(containerized)应用程序”的开源系统。 可以理解成 K8S 是负责自动化运维管理多个容器化程序(比如 Docker)的集群&#…...

Electron + Vue3 + Vite + TS 构建桌面应用

之前是使用React、Electron、TS和webpack来构建桌面应用的。虽然功能齐全,但是打包等等开发的体验不太理想,总感觉太慢了。作为一个开发者,我们总是希望,执行构建命令后,可以快速打包或者启动本地应用,且通过更少的配置,来完成开发体验。 现在的vite已经得到广泛的应用…...

springboot访问请求404的原因

是记录,可能出现错误 可能出现的原因 1.你请求的URL路径不对,比如说你请求的路径是/usr/list,GET方法,但是你UserController上面的RequestMapping是这个样子:RequestMapping(“user”),有可能哈 2.前端的请求时GET方法,后端对应的处理函数的方…...

网络安全零基础该如何自学?

一、为什么选择网络安全? 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地,网络安全行业地位、薪资随之水涨船高。 未来3-5年,是安全行业的黄金发展期,提前踏入…...

Git(丢失stash数据恢复)

在这里总结一下昨天遇到的问题,我本想将本地代码push到远端仓库,依次运行了以下命令 git init //初始化 git add . //将本地代码添加到暂存区 git commit -m 注释 //将暂存区内容添加到本地仓库中。 结果这时发生了代码冲突,我的代码全没了&a…...

Maven依赖管理

依赖特性: 1、依赖配置 2、依赖传递 3、可选依赖 4、排除依赖 5、依赖范围...

【电网技术复现】考虑实时市场联动的电力零售商鲁棒定价策略(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

R语言中数据重塑(长宽表的转化)

学习笔记,仅供学习使用。 目录 1-什么是整洁的数据? 2-宽表变成长表 示例1: 示例2: 示例3: 3-长表变宽表 示例1: 示例2: 1-什么是整洁的数据? 按照Hadley的表述&#xf…...

C# Blazor 学习笔记(10):依赖注入

文章目录 前言Blazor 依赖注入依赖注入用于解决什么问题?依赖注入的生命周期。测试代码 总结 前言 Blazor 具有前后端不分离模式,但是如何直接调用需要一定的设置 Blazor 依赖注入 依赖注入在spring里面很常见,毕竟.NET 是个巨型融合怪。只…...

接口请求(get、post、head等)详解

一.接口请求的六种常见方式: 1、Get 向特定资源发出请求(请求指定页面信息,并返回实体主体) 2、Post 向指定资源提交数据进行处理请求(提交表单、上传文件),又可能导致新的资源的建…...

【【萌新的STM32学习-4】】

萌新的STM32学习-4 STM32系统框架 1.1 Cortex M 内核& 芯片 F1有四个驱动单元 四个被动单元 AHB 高级高性能总线 APB 高级外围总线 部分系统结构 最上面的ICode 总线直接连接到了内部Flash 不需要通过总线矩阵 . D Code 总线(D - Bus) 这是Cort…...

C++ Primer Plus第五章 习题

目录 复习题: 1.入口条件循环和出口条件循环之间的区别是什么?各种c循环分别属于其中的哪一种? 2.如果下面的代码片段是有效程序的组成部分,它将打印什么内容? 3.如果下面的代码片段是有效程序的组成部分&#xff0…...

软考A计划-系统集成项目管理工程师-信息文档和配置管理-上

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 👉关于作者 专注于Android/Unity和各种游…...

Vue 路由 路由守卫

路由守卫 正如其名, vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。简单来说,就是在路由跳转 时候的一些钩子,当从一个页面跳转到另一个页面时,可以在跳转前、中、后做一些事情。 当你打开一个页面的前后需…...

基于springboot的课程作业管理系统【附开题|ppt|万字文档(LW)和搭建文档】

主要功能 学生登录: ①首页、个人中心:修改密码、个人信息管理等 ②公告信息管理、课程信息管理、学生选课管理、作业布置管理、作业提交管理、作业评分管理、课程评价管理、课程资源管理 教师登录: ①首页、个人中心:修改密码、…...

关于个人微信API接口的开发

个人微信开发API接口可拓展功能说明 1、个人微信多账号管理、聚合聊天、多个微信号同时登陆、多个微信号集中在一个窗口进行聊天,实现一人多号同时沟通快速提升沟通效率,提升微信营销效率。 2、客服灵活分配:客服主管可自由分配微信号给指定…...

华为PMS API client token auth failed

对接华为pms时出现问题,提示华为PMS API client token auth failed 主要是权限的问题,创建项目的时候选择N/A...

【Java面试丨消息中间件】Kafka

一、kafka是如何保证消息不丢失 1. 介绍 使用kafka在消息的收发过程都有可能会出现消息丢失 (1)生产者发送消息到broker丢失 (2)消息在broker中存储丢失 (3)消费者从broker接收消息丢失 2. 生产者发送消…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...