Linux系统编程——网络编程的学习

news2025/1/12 4:44:36

Linux系统编程学习相关博文

  1. Linux系统编程——文件编程的学习
  2. Linux系统编程——进程的学习
  3. Linux系统编程——进程间通信的学习
  4. Linux系统编程——线程的学习

Linux系统编程——网络编程的学习

  • 一、概述
    • 1. TCP/UDP
    • 2. 端口号
    • 3. 字节序
    • 4. Sockt服务器和客户端的开发步骤
      • 1. 服务器
      • 2. 客户端
  • 二、网络编程API
  • 三、API介绍
    • 1. socket函数
    • 2. bind函数
    • 3. listen函数
    • 4. accept函数
    • 5. connect函数
    • 6. inet_aton函数
    • 7. inet_ntoa函数
    • 8. htons函数
  • 四、API的使用例子

一、概述

1. TCP/UDP

  1. TCP面向连接( 如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
  2. TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
  3. TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低 (对实时应用很有用,如IP电话,实时视频会议等)
  4. 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
  5. TCP首部开销20字节;UDP的首部开销小,只有8个字节
  6. TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

2. 端口号

一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等。这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP 地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的。端口提供了一种访问通道,服务器一般都是通过知名端口号来识别的。例如,对于每个TCP/IP实现来说,FTP服务器的TCP端口号都是21,每个Telnet服务器的TCP端口号都是23,每个TFTP (简单文件传送协议) 服务器的UDP端口号都是69。

3. 字节序

  1. 小端字节序 (Little endian):将低序字节存储在起始地址
  2. 大端字节序 (Big endian):将高序字节存储在起始地址
  3. 网络字节序 = 大端字节序

4. Sockt服务器和客户端的开发步骤

1. 服务器

  1. 创建套接字
  2. 为套接字添加信息 (IP地址和端口号)
  3. 监听网络连接
  4. 监听到有客户端接入,接受一个连接
  5. 数据交互
  6. 关闭套接字,断开连接

2. 客户端

  1. 创建套接字
  2. 连接服务器 (输入服务器IP地址和端口号)
  3. 数据交互
  4. 关闭套接字,断开连接
    在这里插入图片描述

二、网络编程API

在Linux系统中,操作系统提供了一系列的API,详细看下图

创建套接字	socket()
绑定		bind()
监听		listen()
连接(服务器)		accept()
连接(客户端)		connect()

地址转换		inet_aton() / inet_ntoa
字节序转换	htons() / htonl() / ntohs() / ntohl()

三、API介绍

1. socket函数

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

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

 1. 函数功能:创建套接字
 2. 形参说明:
domain:指明所使用的协议族,通常为AF_INET,表示互联网协议族(TCP/IP协议族)
	- AF_INET	IPV4因特网域
	- AF_INET6	IPv6因特网域 
	- AF_UNIX 	Unix域 
	- AF_ROUTE 	路由套接字
	- AF_KEY 	密钥套接字 
	- AF_UNSPEC 未指定
type:指定 socket 的类型
	- SOCK STREAM
	 	流式套接字提供可靠的、面向连接的通信流,它使用 TCP 协议,从而保证了数据传输的正确性和顺序性
	- SOCK DGRAM
	 	数据报套接字定义了一种无连接的服,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议 UDP
	- SOCK RAW
		允许程序使用底层协议,原始套接字允许对底层协议如 IP 或 ICMP 进行直接访问,功能强大但使用较为不便,主要用于一些协议的开发
protocal:通常赋值为0
	- 0 选择 type 类型对应的默认协议
	- IPPROTO_TCP TCP 传输协议
	- IPPROTO_UDP UDP 传输协议
	- IPPROTO_SCTP SCTP 传输协议
	- IPPROTO_TIPC TIPC 传输协议
3. 返回值:成功,返回套接字的文件描述符;失败,返回-1

2. bind函数

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

1. 函数功能:用于绑定IP地址和端口号到sockfd
2. 形参说明:
sockfd:调用socket函数返回的套接字描述符
addr:是一个指向包含有本机 IP 地址及端口号等信息的 sockaddr 类型的指针,指向要绑定给 sockfd 的协议地址结构,这个地址结构根据地址创建 socket 时的地址协议族的不同而不同(该结构体原型在下方)
addrlen:addr的大小

struct sockaddr结构体原型:
	struct sockaddr {
		sa_family_t sa_family;
		char        sa_data[14];
	};
可同等替换为:
	struct sockaddr_in {
		__kernel_sa_family_t  sin_family; /* 协议族 */
		__be16  sin_port;   /* 端口号 */
		struct in_addr  sin_addr;   /* IP地址结构体 */
		
		/* 填充到结构体sockaddr的大小,没有实际意义,只是为跟sockaddr结构体在内存中对齐,这样两者才能相互转换 */
		unsigned char  __pad[__SOCK_SIZE__ - sizeof(short int) -
		sizeof(unsigned short int) - sizeof(struct in_addr)];
	};
3. 返回值:成功,返回0;失败,返回-1

3. listen函数

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int listen(int sockfd, int backlog);

1. 函数功能:监听设置,设置能处理的最大连接数
	- 设置能处理的最大连接数,listen() 并末开始接受连线,只是设置 sockect 的 listen 模式,listen 函数只用于服务端,服务路进程不知道要与谁连接,因此,它不会主动地要求与某个进程连接,只是一直监听是否有其他客户进程与之连接,然后响应该连接请求,并对它做出处理,一个服务进程可以同时处理多个客户进程的连接。主要就两个功能:将一个未连接的套接字转换为一个被动套接字(监听),规定内核为相应套接字排队的最大连接数。
	- 内核为任何一个给定监听套接字维护两个队列:
		- 未完成连接队列,每个这样的 SYN 报文段对应其中一项:已由某个客户发出并到达服务醒,而服务器正在等待完成相应的 TCP 二次握手过程。这些套接字处于 SYN REVD 状态;
		- 已完成连接队列,每个已完成 TCP 三次握手过程的客户端对应其中一项。这些套接字处于 ESTABLISHED 状态
2. 形参说明:
sockfd:调用socket函数返回的套接字描述符
backlog:请求队列允许的最大请求数
3. 返回值:成功,返回0;失败,返回-1

4. accept函数

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

1. 函数功能:用于从已完成连接队列队头返回下一个已完成的连接。如果已完成连接队列为空,那么进程被投入睡眠
2. 形参说明:
sockfd:调用socket函数返回的套接字描述符
addr:用来返回已连接的对端(客户端)的协议地址
addrlen:客户端地址长度
3. 返回值:该函数的返回值是一个新的套接字描述符,返回值是表示已连接的套接字描述符,而第一个参数是服务器监听套接字描述符。一个服务器通常仅仅创建一个监听套接字,它在该服务器的生命周期内一直存在,内核为每个由服务器进程接受的客户连接创建一个已连接套接字(表示 TCP 三次挥手已完成),当服务器完成对某个给定客户的服务时,相应的已连接套接字就会被关闭。成功,返回0;失败,返回-1

5. connect函数

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

1. 函数功能:绑定之后的client端(客户端),与服务器建立连接
2. 形参说明:
sockfd:目的服务器的套接字描述符
addr:服务器端的IP地址和端口号的结构体指针
addrlen:addr大小
3. 返回值:成功,返回0;失败,返回-1

6. inet_aton函数

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int inet_aton(const char *cp, struct in_addr *inp);
       char *inet_ntoa(struct in_addr in);

1. 函数功能:将字符串形式的 IP 地址转为网络能识别的格式
2. 形参说明:
cp:IP地址
inp:存放IP地址的结构体指针(如下所示)

struct sockaddr结构体原型:
	struct sockaddr {
		sa_family_t sa_family;
		char        sa_data[14];
	};
可同等替换为:
	struct sockaddr_in {
		__kernel_sa_family_t  sin_family; /* 协议族 */
		__be16  sin_port;   /* 端口号 */
		struct in_addr  sin_addr;   /* IP地址结构体 */
		
		/* 填充到结构体sockaddr的大小,没有实际意义,只是为跟sockaddr结构体在内存中对齐,这样两者才能相互转换 */
		unsigned char  __pad[__SOCK_SIZE__ - sizeof(short int) -
		sizeof(unsigned short int) - sizeof(struct in_addr)];
	};

7. inet_ntoa函数

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

char *inet_ntoa(struct in_addr in);

1. 函数功能:将网络格式的IP地址转为字符串格式
2. 形参说明:
in:存放IP地址的结构体(结构体原型见上方)

8. htons函数

#include <arpa/inet.h>

uint16_t htons(uint16_t hostshort);

1. 函数功能:返回网络字节序的值(关于什么是字节序请看概述部分),用来转换端口号
2. 形参说明:
hostshort:转换的端口号。h代表host,n代表net,s代表short(两个字节),l代表long(4个字节),通过上面的4个函数可以实现主机字节序和网络字节序之间的转换。有时可以用INADDR_ANY,INADDR_ANY指定地址让操作系统自己获取

四、API的使用例子

实现功能:服务器可以接收各个客户端的信息,每隔五秒服务器向连接的客户端发送信息(类似心跳包)
1. 服务端

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 #include <sys/types.h>          /* See NOTES */
  6 #include <sys/socket.h>
  7 #include <arpa/inet.h>
  8 #include <netinet/in.h>
  9 
 10 //1. int socket(int domain, int type, int protocol);
 11 //2. int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
 12 //3. uint16_t htons(uint16_t hostshort);
 13 //4. int inet_aton(const char *cp, struct in_addr *inp);
 14 //5. int listen(int sockfd, int backlog);
 15 //6. int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
 16 
 17 int main(int argc, char **argv)
 18 {
 19     int mark = 0;
 20     int c_fd = 0;
 21     int s_fd = 0;
 22     int s_bind = 0;
 23     int c_lent = 0;
 24     int n_read = 0;
 25     int s_listen = 0;
 26 
 27     char msg[128] = {'\0'};
 28     char readBuf[128] = {'\0'};
 29     char sendBuf[128] = {'\0'};
 30     //char *sendBuf = "Thank you for your message";
 31 
 32     struct sockaddr_in s_addr;
 33     struct sockaddr_in c_addr;
 34 
 35     memset(&s_addr, 0, sizeof(struct sockaddr_in));
 36     memset(&c_addr, 0, sizeof(struct sockaddr_in));
 37 
 38     if(argc != 3){
 39         printf("Please input three params\n");
 40         exit(-1);
 41     }
 42 
 43     //1. socket
 44     s_fd = socket(AF_INET, SOCK_STREAM, 0);
 45     if(s_fd == -1){
 46         perror("Create socekt failed:");
 47         exit(-1);
 48     }
 49 
 50     //2. bind
 51     s_addr.sin_family = AF_INET;
 52     s_addr.sin_port = htons(atoi(argv[2]));
 53     inet_aton(argv[1], &s_addr.sin_addr);
 54 
 55     s_bind = bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));
 56     if(s_bind == -1){
 57         perror("Bind failed:");
 58         exit(-1);
 59     }
 60 
 61     //3. listen
 62     s_listen = listen(s_fd, 10);
 63     if(s_listen == -1){
 64         perror("Listen failed:");
 65         exit(-1);
 66     }
 67 
 68     printf("listen...\n");
 69 
 70     //4. accept
 71     while(1){
 72         c_lent = sizeof(struct sockaddr_in);
 73         c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &c_lent);
 74         if(c_fd == -1){
 75             perror("Accept failed:");
 76             exit(-1);
 77         }
 78 
 79         printf("Get connect: %s\n", inet_ntoa(c_addr.sin_addr));
 80 
 81         mark++;
 82 
 83         if(fork() == 0){
 84             while(1){
 85                 memset(sendBuf, '\0', sizeof(sendBuf));
 86 
 87                 sprintf(sendBuf, "Welcome No.%d client", mark);
 88                 write(c_fd, sendBuf, sizeof(sendBuf));
 89                 sleep(5);
 90 
 91                 if(fork() == 0){
 92                     while(1){
 93                         memset(msg, '\0', sizeof(msg));
 94                         memset(readBuf, '\0', sizeof(readBuf));
 95 
 96                         n_read = read(c_fd, readBuf, sizeof(readBuf));
 97                         if(n_read == -1){
 98                             printf("Read failed:");
 99                         }else{
100                             sprintf(msg, "Get No.%d message: %s", mark, readBuf);
101                             printf("%s\n", msg);
102                         }
103                     }
104                 }
105             }
106         }
107     }
108 
109     return 0;
110 }

2. 客户端

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 #include <sys/types.h>          /* See NOTES */
  6 #include <sys/socket.h>
  7 #include <arpa/inet.h>
  8 #include <netinet/in.h>
  9 
 10 //1. int socket(int domain, int type, int protocol);
 11 //2. int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
 12 //3. int inet_aton(const char *cp, struct in_addr *inp);
 13 //4. char *inet_ntoa(struct in_addr in);
 14 
 15 int main(int argc, char **argv)
 16 {
 17     int c_fd = 0;
 18     int n_read = 0;
 19 
 20     char readBuf[128] = {'\0'};
 21     char sendBuf[128] = {'\0'};
 22     //char *sendBuf = "Message from client";
 23 
 24     struct sockaddr_in c_addr;
 25 
 26     memset(&c_addr, 0, sizeof(struct sockaddr_in));
 27 
 28     if(argc != 3){
 29         printf("Please input three params\n");
 30         exit(-1);
 31     }
 32 
 33     //1. socket
 34     c_fd = socket(AF_INET, SOCK_STREAM, 0);
 35     if(c_fd == -1){
 36         perror("Create socekt failed:");
 37         exit(-1);
 38     }
 39 
 40     //2. connect
 41     c_addr.sin_family = AF_INET;
 42     c_addr.sin_port = htons(atoi(argv[2]));
 43     inet_aton(argv[1], &c_addr.sin_addr);
 44 
 45     if(connect(c_fd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr_in)) == -1){
 46         perror("Connect failed:");
 47         exit(-1);
 48     }
 49 
 50     while(1){
 51         memset(sendBuf, '\0', sizeof(sendBuf));
 52 
 53         printf("input :");
 54         gets(sendBuf);
 55         write(c_fd, sendBuf, strlen(sendBuf));
 56 
 57         if(fork() == 0){
 58             while(1){
 59                 memset(readBuf, '\0', sizeof(readBuf));
 60 
 61                 n_read = read(c_fd, readBuf, sizeof(readBuf));
 62                 if(n_read == -1){
 63                     printf("Read failed:");
 64                 }else{
 65                     printf("Get server message: %s\n", readBuf);
 66                 }
 67             }
 68         }
 69     }
 70 
 71     return 0;
 72 }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1030346.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络编程 day4

1->广播模型 接收方 发送方 2->组播模型 接收方 发送方 3->多进程并发服务器 4->多线程并发服务器

openssl 交叉编译(uclibc)

参考文章 openssl 交叉编译_GeYi1998的博客-CSDN博客 本地实际操作一遍,和网上的文章有些不同. 先下载源码 /source/index.html 使用 1.1.1w的版本,最新的3.0.11试了,编译不过,很多gcc的写法问题(error: initializer element is not constant) 解压到 Document 目录下, h…

视频汇聚/视频云存储/视频监控管理平台EasyCVR分发rtsp流起播慢优化步骤详解

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

iOS自动化测试方案(一):MacOS虚拟机保姆级安装Xcode教程

文章目录 一、环境准备二、基础软件三、扩展&#xff1a;usb拓展插件 一、环境准备 1、下载VMware虚拟机的壳子&#xff0c;安装并注册软件(可以百度注册码)&#xff0c;最新版本&#xff1a;v17 2、下MacOS系统iOS镜像文件&#xff0c;用于vmware虚拟机安装&#xff0c;当前镜…

如何用一行CSS实现10种现代布局

现代 CSS 布局使开发人员只需按几下键就可以编写十分有意义且强大的样式规则。上面的讨论和接下来的帖文研究了 10 种强大的 CSS 布局&#xff0c;它们实现了一些非凡的工作。 超级居中&#xff1a;place-items: center 对于第一个“单行”布局&#xff0c;让我们解决所有 CSS…

使用 PyTorch 的计算机视觉简介 (3/6)

一、说明 在本单元中&#xff0c;我们将了解卷积神经网络&#xff08;CNN&#xff09;&#xff0c;它是专门为计算机视觉设计的。 卷积层允许我们从图像中提取某些图像模式&#xff0c;以便最终分类器基于这些特征。 二、卷积神经网络 计算机视觉不同于通用分类&#xff0c;因…

虚拟机中window/ubuntu系统如何联网?

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 参考博客 &#xff08;1&#xff09;VMware虚拟机中Windows11无法连接网络 &#xff08;2&#xff09;图解vmware虚拟机win8无线上网 &#xff08;3&#xff09;VMware中VMnet0、VMnet1、VMnet8是什么 &…

PyTorch深度学习(七)【循环神经网络-提高】

数据集文末分享。 模型&#xff1a; 做完padding之后&#xff0c;就可以转换为张量了。 bidirectional是是否使用双向RNN: 输出隐层两个&#xff1a; 代码&#xff1a; import csvimport timeimport matplotlib.pyplot as pltimport numpy as npimport mathimport gzip # 用…

巨人互动|Facebook海外户Facebook内容的类型

随着人们日益依赖的社交媒体来进行信息获取与交流&#xff0c;Facebook作为全球最大的社交媒体平台之一&#xff0c;那么Facebook的内容都有哪些类型呢&#xff1f;下面小编来讲讲吧&#xff01; 1、实时发生的事 我们需要实时了解时事动态&#xff0c;这样可以使用户对品牌发…

【网络层】IP协议

文章目录 IP协议1. 前提认识(1) IP的定位和作用(2) IP地址的构成(3) 基本概念 2. 协议头格式(1) 两个核心问题 3. 网段划分(重要)(1) 为什么要网段划分(2) 概念(3) 子网划分方案(4) 模拟子网划分 4. 特殊的IP地址5. IP地址的数量限制6. 私有IP地址和公网IP地址7. 路由及路由表(…

学习记忆——宫殿篇——记忆宫殿——记忆桩——火车+外院+客厅+卧室

护板 警示灯 烟筒 采集箱 司炉室 桥 电线杆 棚顶 车厢 护栏 植物 石阶 水泥台 竹门 树干 躺椅 柱子 墙 池 洞 方灯 枕头 树 浴池 墙 射灯 藤条 浴巾框 耳环 窗户 灯 沙发 壁炉 吊灯 兵马俑 门 石佛 沙发椅 圆木 弧形木箱盖 床 窗帘 画板 纸伞 花 沙发背 颜料 抽屉

Hadoop-sqoop

sqoop 1. Sqoop简介及原理 简介&#xff1a; Sqoop是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysq1.postgresql..)间进行数据的传递&#xff0c;可以将一个关系型数据库&#xff08;例如: MySQL ,Oracle ,Postgres等&#xff09;中的数据导进到Hadoop 的HDFS中&…

【AI视野·今日Robot 机器人论文速览 第三十七期】Wed, 20 Sep 2023

AI视野今日CS.Robotics 机器人学论文速览 Wed, 20 Sep 2023 Totally 53 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Machine Learning-Driven Burrowing with a Snake-Like Robot Authors Sean Even, Holden Gordon, Hoeseok Yang, Yasemin Ozk…

《软件方法》第1章2023版连载(03)建模工作流

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 1.2 建模工作流 1.2.1 建模工作流ABCD 如何能做好需求和设计&#xff0c;达到“低成本制造好卖的系统”的目标&#xff1f;并非喊喊口号就可以&#xff0c;需要静下心来学习和实践一…

基于知识蒸馏的两阶段去雨去雪去雾模型学习记录(一)

前面完成了基于知识蒸馏的去雨去雪去雾模型大的部署与训练&#xff0c;下面则进行代码的学习。 使用debug的方式进行代码的学习。 首先是网络结构展示&#xff1a;轻易不要打开&#xff0c;这个模型太复杂了。说到底倒不是多复杂&#xff0c;就是层数太多了 Net((conv_input):…

玩玩“小藤”开发者套件 Atlas 200I DK A2 之VSCode远程连接

玩玩“小藤”开发者套件 Atlas 200I DK A2 之VSCode远程连接 0. 背景1. VSCode 安装 Remote - SSH 插件2. 安装 OpenSSH 组件3. VSCode SSH 连接 Atlas 200I DK A24. 打开远程文件夹 0. 背景 总所周知&#xff0c;英伟达的GPU供不应求&#xff0c;还各种限制。华为推出了升腾A…

ChatGLM2-6B 部署与微调

文章目录 一、ChatGLM-6B二、ChatGLM2-6B三、本地部署ChatGLM2-6B3.1 命令行模式3.2 网页版部署3.3 本地加载模型权重3.4 模型量化3.5 CPU部署3.6 多卡部署 四、P-tuning v2微调教程4.1 P-tuning v2 原理4.2 P-tuning v2微调实现4.2.1 安装依赖&#xff0c;下载数据集4.2.2 开始…

好题记录 Leetcode 394.字符串解码 中等难度

方法一&#xff1a;递归 思路很简单&#xff0c;比较好理解&#xff0c;注意细节处理&#xff01;&#xff01;&#xff01; class Solution { public:string decodeString(string s) {string ans;for(int i0;s[i]!0;i){if(s[i]>a&&s[i]<z)anss[i];if(s[i]>…

CentOS 7系统安装与配置、常用100条操作命令

CentOS 7 是一个广泛使用的开源 Linux 操作系统&#xff0c;它是 Red Hat Enterprise Linux (RHEL) 的一个免费重建版本&#xff0c;以稳定性和安全性而著称。在 CentOS 7 上安装虚拟机通常使用虚拟化技术&#xff0c;如 VirtualBox 或 VMware 等。以下是 CentOS 7 的简要介绍以…

外国固定资产管理系统功能有哪些

很多公司都在寻找提高自己资产管理效益的方法。为了满足这一要求&#xff0c;国外的固定资产管理系统已经发展成多种形式。以下是国外一些常见的固定资产管理系统的特点:自动化和智能化:许多现代固定资产管理系统采用自动化和数字化技术&#xff0c;以简化流程&#xff0c;减少…