【Linux】基于UDP/TCP套接字编程与守护进程

目录

一、网路套接字编程

(一)基础概念

1、源IP地址与目的IP地址

2、端口号

3、TCP与UDP

4、网络字节序

(二)套接字编程接口

1、socket 常见API

2、sockaddr结构

(三)UDP套接字

1、UDP服务器创建流程

2、UDP客户端创建流程

3、创建 socket 套接字

4、绑定 socket 端口号

5、服务器客户端数据的发送与接收

(四)TCP套接字

1、TCP服务器创建流程

2、TCP客户端创建流程

3、创建 socket 套接字

4、绑定 socketI P地址与端口号

5、服务器设置监听状态

6、服务器获取客户端连接请求

7、客户端连接请求

二、守护进程

(一)概念

(二)函数接口

(三)模拟实现


一、网路套接字编程

(一)基础概念

1、源IP地址与目的IP地址

        在网络中,IP地址就是用来标识处于网络中的一台主机的地址,而源IP地址就是发送主机的地址,而目的IP地址就是接收主机的IP地址。

2、端口号

        在网路通信中,仅仅知道主机的地址是不够的。例如:当我们打开QQ并发送一条消息时,当接收主机收到该数据时是无法确定该数据是发给QQ的还是微信的。因此在网路通信中还需要 端口号

        端口号是传输层协议的内容。

  • 端口号是一个2字节16位的整数;
  • 端口号用于标识一台主机上的进程,在网络通信中,通过端口可以得知该数据一个交给哪一个进程;
  • IP地址 + 端口号 能够标识网络上的某一台主机的某一个进程;
  • 一个端口号只能被一个进程占用,但一个进程可以占用多个端口号。

        网络通信的本质实际时进程间通信,那为什么不直接使用进程 PID 来代替端口号呢?

        (1)使网络通信与操作系统解耦;

        (2)我们知道进程 PID 是由操作系统给出的,当服务器重启后其PID很可能会发生改变,如果直接使用 PID 作为标识不便于网络通信。

        因此在网络通信中,不仅有源IP地址和目的IP地址,还有源端口号和目的端口号。除此之外,操作系统内部维护了一张哈希表,用于映射端口号到进程PCB的地址。

3、TCP与UDP

       TCP( 传输控制协议):

  • 传输层协议
  • 有链接
  • 可靠传输
  • 面向字节流

        UDP(用户数据报协议):

  • 传输层协议
  • 无连接
  • 不可靠传输
  • 面向数据报

4、网络字节序

        内存中的很多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分,网络数据流同样有大端小端之分。

  • TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节
  • 如果发送主机是小端字节序,需先将数据转换为大端后发送;如果发送主机是大端字节序,则直接进行发送即可;但在实际编程时考虑到代码移植性,无论大端机还是小段机,向网络发送数据还是从网络接收数据统一进行转换;
  • 发送主机和接收主机都按照低地址到高地址发送接收数据

        考虑到网络字节序的问题,C语言为我们提供了库函数。

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

        以上便是字节序转换函数,例如 htons() 表示将16位短整数从主机字节序转换到网络字节序,至于具体是否需要进行转换由函数内部决定。

        同样对于IP地址也需要进行转换。

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
//将点分十进制字符串转换为 uint32_t 的网络字节序
in_addr_t inet_addr(const char *cp);
in_addr_t inet_network(const char *cp);
//将32位的IPv4地址转化为点分十进制字符串
char *inet_ntoa(struct in_addr in);
struct in_addr inet_makeaddr(int net, int host);
in_addr_t inet_lnaof(struct in_addr in);
in_addr_t inet_netof(struct in_addr in);

(二)套接字编程接口

1、socket 常见API

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
// 绑定端口号 (TCP/UDP, 服务器) 
int bind(int socket, const struct sockaddr *address, socklen_t address_len);
// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address, socklen_t* address_len);
// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)

2、sockaddr结构

        socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6等,各种网络协议的地址格式并不相同。

        在使用socket API时,无论是网络套接字还是域间套接字都需要强转为 struct sockaddr 类型,通过传入参数 socketaddr 的前16位操作系统可以分辨是哪种套接字,从而在内部切换对应的套接字结构。

//sockaddr 结构
/* Structure describing a generic socket address.  */
struct sockaddr
  {
    __SOCKADDR_COMMON (sa_);	/* Common data: address family and length.  */
    char sa_data[14];		/* Address data.  */
  };

//sockaddr_in 结构
/* Structure describing an Internet socket address.  */
struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port;			    /* Port number.  */
    struct in_addr sin_addr;		/* Internet address.  */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
			   __SOCKADDR_COMMON_SIZE -
			   sizeof (in_port_t) -
			   sizeof (struct in_addr)];
  };

//in_addr结构
/* Internet address.  */
typedef uint32_t in_addr_t;
struct in_addr
  {
    in_addr_t s_addr;
  };

(三)UDP套接字

1、UDP服务器创建流程

1、创建套接字;

2、绑定IP地址和端口号;

3、接收数据、处理数据和发送数据。

2、UDP客户端创建流程

1、创建套接字;

2、客户端不需要显式 bind IP地址与端口号,该动作由操作系统完成;

3、发送数据、接收数据和对数据进行处理。

3、创建 socket 套接字

NAME
       socket - create an endpoint for communication
SYNOPSIS
       #include <sys/socket.h>
       int socket(int domain, int type, int protocol);
RETURN VALUE
       Upon  successful  completion, socket() shall return a non-negative 
integer, the socket file descriptor. Otherwise, a value of -1 shall be returned 
and errno set to indicate the error.

用途:服务器与客户端创建 socket 文件描述符(TCP/UDP)

参数

  • domain:指定套接字的协议族,常见的协议族有AF_INET(IPv4网络通信)、AF_UNIX/AF_LOCAL(本地通信)
  • type:指定套接字的类型。常见的类型有SOCK_STREAM(流套接字)和SOCK_DGRAM(数据报套接字)。
  • protocol:套接字使用的具体协议,通常与 domain和 type配合使用。一般情况下,可以将其设置为 0,表示由操作系统根据 domain和 type自动选择合适的协议。

返回值:

  • 如果成功会返回一个非负的整型值,表示套接字的文件描述符;
  • 如果失败返回-1,并设置 error 来表示错误原因。

4、绑定 socket 端口号

NAME
       bind - bind a name to a socket
SYNOPSIS
       #include <sys/socket.h>
       int bind(int socket, const struct sockaddr *address,
              socklen_t address_len);
RETURN VALUE
       Upon successful completion, bind() shall return 0; otherwise, -1 shall 
be returned and errno set to indicate the error.

用途:将一个套接字与一个特定的IP地址和端口号绑定

参数:

  • socket:套接字的文件描述符;
  • address:指向 struct sockaddr 类型的指针,包含套接字将要绑定的地址信息。具体的地址结构根据协议族的不同而有所区别;
  • address_len:地址结构的长度,通常使用 sizeof 来获取。

5、服务器客户端数据的发送与接收

NAME
       sendto - send a message on a socket
SYNOPSIS
       #include <sys/socket.h>
       ssize_t sendto(int socket, const void *message, size_t length,
              int flags, const struct sockaddr *dest_addr,
              socklen_t dest_len);
RETURN VALUE
       Upon successful completion, sendto() shall return the number of bytes 
sent. Otherwise, -1 shall be returned and errno set to indicate the error.

用途:从已连接的 socket 中发送数据,常用于通过 UDP 协议或其他支持无连接的协议发送数据。

参数:

  • socket:套接字的文件描述符;
  • message:发送数据的地址;
  • length:发送数据的长度;
  • flags:控制发送操作的标志,通常为0;
  • dest_addr:指向 sockaddr 结构体指针,包含目标地址的信息;
  • dest_len:dest_addr 的长度,以字节为单位。

返回值:

  • 成功时返回发送的字节数;
  • 失败时返回-1并设置错误码。
NAME
       recvfrom - receive a message from a socket
SYNOPSIS
       #include <sys/socket.h>
       ssize_t recvfrom(int socket, void *restrict buffer, size_t length,
              int flags, struct sockaddr *restrict address,
              socklen_t *restrict address_len);
RETURN VALUE
       Upon successful completion, recvfrom() shall return the length of the 
message in bytes. If no messages are available to be received and the peer 
has performed an orderly shutdown,  recvfrom()  shall return 0. Otherwise, 
the function shall return -1 and set errno to indicate the error.

用途:从套接字接收数据的函数,它可以接收来自网络的消息,并允许用户指定用于接收消息的缓冲区,常用于 UDP 协议和其他无连接协议中。

参数:

  • socket:套接字的文件描述符;
  • buffer:指向内存缓冲区的指针,用于存储接收到的数据;
  • length:buffer缓冲区的大小;
  • flags:控制接收操作的标志,通常为 0;
  • address:指向 sockaddr 结构体的指针,接收端的信息由此填充;
  • address_len:指向 address 结构体的指针,表示该结构体的长度。

返回值:

  • 成功时返回接收到的字节数;
  • 若无消息接收且接收方关闭连接则返回0;
  • 失败时返回-1并设置错误码。

(四)TCP套接字

1、TCP服务器创建流程

1、创建套接字;

2、绑定IP地址和端口号;

3、设置 socket 处于监听状态;

4、等待获取客户端连接请求;

5、接收数据、处理数据和发送数据。

2、TCP客户端创建流程

1、创建套接字;

2、客户端不需要显式 bind IP地址与端口号,该动作由操作系统完成;

3、向服务器发送连接请求;

4、发送数据、接收数据和对数据进行处理。

3、创建 socket 套接字

         同UDP,但传入参数不同。

//UDP
udpFd = socket(AF_INET, SOCK_DGRAM, 0);
//TCP
tcpFd = spcket(AF_INET, SOCK_STREAM, 0);

4、绑定 socketI P地址与端口号

        同UDP,但传入参数不同。

5、服务器设置监听状态

NAME
       listen - listen for socket connections and limit the queue of incoming 
connections
SYNOPSIS
       #include <sys/socket.h>
       int listen(int socket, int backlog);
RETURN VALUE
       Upon successful completions, listen() shall return 0; otherwise, -1 
shall be returned and errno set to indicate the error.

用途:在一个套接字上监听来自客户端的连接请求,主要用于面向连接的协议(如 TCP)。

参数:

  • socket:套接字的文件描述符;
  • blcklog:表示在套接字上等待连接的最大队列长度。

返回值:

  • 成功时返回0;
  • 失败时返回-1并设置错误码。

6、服务器获取客户端连接请求

NAME
       accept - accept a new connection on a socket
SYNOPSIS
       #include <sys/socket.h>
       int accept(int socket, struct sockaddr *restrict address,
              socklen_t *restrict address_len);
RETURN VALUE
       Upon successful completion, accept() shall return the non-negative 
file descriptor of the accepted socket. Otherwise, -1 shall be returned and 
errno set to indicate the error.

用途:在一个已监听的套接字上接受一个客户端的连接请求。

参数:

  • socket:套接字的文件描述符;
  • address:指向 sockaddr 结构体的指针,用来存储客户端的地址信息;
  • address_len:指向 socket_t 类型的指针,表示 address 缓冲区的长度。

返回值:

  • 成功时返回一个新的套接字,该文件描述符用于与用户进行数据交换;
  • 失败时返回-1并设置错误码。

7、客户端连接请求

NAME
       connect - connect a socket
SYNOPSIS
       #include <sys/socket.h>
       int connect(int socket, const struct sockaddr *address,
              socklen_t address_len);
RETURN VALUE
       Upon successful completion, connect() shall return 0; otherwise, -1 
shall be returned and errno set to indicate the error.

用途:用于客户端向服务器发起连接请求。

参数:

  • socket:套接字的文件描述符;
  • address:指向 sockaddr 结构体的指针,结构体中包含了目标主机的 IP 地址和端口号等信息
  • address_len:表示结构体 address 的长度。

返回值:

  • 成功时返回0;
  • 失败时返回-1并设置错误码。

二、守护进程

(一)概念

        当我们登录云服务器并使服务器运行时,如果我们退出登录,云服务器上部署的服务器也会被关闭,如何使得部署的服务器不受用户登录注销的影响呢?

        这时候就需要将服务器变为守护进程,守护进程的本质实际是一个孤儿进程。

        当我们登录云服务器时会建立一个会话,一个会话只有一个前台进程和n个后台进程,作业之间可以前后台转换,但这些任务仍有可能收到用户登陆注销的影响。

        而守护进程则是将目标进程独立出去成为一个新的会话,因此便不受用户的影响,可以一直运行下去。

        其中SID则为会话ID,PGID为一个进程组的ID,该ID值与进程组组长的PID相同。

(二)函数接口

        Linux生成守护进程的接口:

NAME
       daemon - run in the background
SYNOPSIS
       #include <unistd.h>
       int daemon(int nochdir, int noclose);
   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
       daemon(): _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)
RETURN VALUE
       (This  function  forks,  and  if the fork(2) succeeds, the parent 
calls _exit(2), so that further errors are seen by the child only.)  On 
success daemon() returns zero.  If an error occurs, daemon() returns -1 
and sets errno to any of the errors specified for the fork(2) and setsid(2).

用途:将程序放到后台运行的函数,通常在编写守护进程(daemon process)时使用。

参数:

  • nochdir:如果这个参数为非零值,表示守护进程在后台运行时不会改变当前工作目录,如果设置为 0,则守护进程会将当前工作目录更改为根目录 /,通常为了避免守护进程锁定在某个目录中,导致无法卸载该目录;
  • noclose:如果该参数为非零值,表示守护进程不会关闭标准输入、标准输出和标准错误输出文件描述符(即不调用 close())。如果设置为 0,守护进程会关闭这些文件描述符。通常,为了避免守护进程继承父进程的终端输出,会关闭这些文件描述符。

返回值:

  • 成功时返回0;
  • 失败时返回-1并设置错误码。

(三)模拟实现

        在实现之前需知道一个函数:

NAME
       setsid - create session and set process group ID
SYNOPSIS
       #include <unistd.h>
       pid_t setsid(void);
RETURN VALUE
       Upon successful completion, setsid() shall return the value of the 
new process group ID of the calling process.  Otherwise, it shall return 
(pid_t)-1 and set errno to indicate the error.

用途:创建一个新的会话(session)并使当前进程成为新的会话领导进程并且不会收到终端的控制。进程组的组长不能调用setsid()函数来创建一个新的会话。

参数:无

返回值:

  • 成功时返回该会话的ID
  • 失败时返回-1并设置错误码
#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cassert>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
//数据黑洞,向它写入的数据会被吃掉,读取数据什么都读不到(不会使进程退出)
#define DEV "/dev/null"
void daemonSelf(const char *currPath = nullptr)
{
    signal(SIGPIPE, SIG_IGN);
    //创建子进程 使子进程成为守护进程
    if (fork() > 0)
        exit(0);
    pid_t id = setsid();
    assert(id != -1);
    int fd = open(DEV, O_RDWR);
    if (fd >= 0)
    {
        //创建成功重定向
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
    }
    else
    {
        //创建失败手动关闭
        close(0);
        close(1);
        close(2);
    }
    if (currPath)
        chdir(currPath);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【图像处理】:两幅图中相同区域的相似度比较

两幅图中相同区域的相似度比较 1.OpenCV和Python实现的两幅图相似度衡量方法1. 均方误差&#xff08;MSE&#xff09;2. 结构相似性指数&#xff08;SSIM&#xff09;图像协方差能显示结构特征的原因 3. 直方图相似度4. 特征点匹配5. 相关系数&#xff08;Pearson Correlation&…

[python脚本]论文1.(一)CPU/内存数据分析和分组

CPU 收集到的CPU数据&#xff0c;格式如下&#xff1a; 由于这里6个数据为一组来收集latency的数据以及各个分位值的数据&#xff0c;而本质上每一行都是一次完整的测试&#xff0c;因此这里将这个csv文件分为两个文件&#xff0c;第一个是和latency相关的&#xff0c;将6条数…

綫性與非綫性泛函分析與應用_1.例題(下)-半母本

第1章 實分析與函數論:快速回顧(下) 五、基數;有限集和無限集相關例題 例題1:集合基數的判斷 判斷集合和集合B=\{a,b,c,d,e\}的基數關係。 解析: 可以構造一個雙射,例如,,,,。 所以,兩個集合具有相同的基數。 例題2:可數集的證明 證明整數集是可數集。 解析: …

MQTT实现智能家居------3、源码分析(超详细)

一、连接服务器 1、初始化&#xff1a; mqtt_log_init();是一个空函数&#xff0c;自己定义宏 client mqtt_lease();//创建一个client结构体&#xff0c;从此以后client代表客户端 platform_memory_alloc();//是一个分配内存的总函数&#xff0c;可以适用于Linux、FreeRTos…

Qt常用控件之日历QCalendarWidget

日历QCalendarWidget QCalendarWidget 是一个日历控件。 QCalendarWidget属性 属性说明selectDate当前选中日期。minimumDate最小日期。maximumDate最大日期。firstDayOfWeek设置每周的第一天是周几&#xff08;影响日历的第一列是周几&#xff09;。gridVisible是否显示日历…

智慧废品回收小程序php+uniapp

废品回收小程序&#xff1a;数字化赋能环保&#xff0c;开启资源循环新时代 城市垃圾治理难题&#xff0c;废品回收小程序成破局关键 随着城市化进程加速与消费水平提升&#xff0c;我国生活垃圾总量逐年攀升&#xff0c;年均增速达5%-8%&#xff0c;其中超30%为可回收物。然…

SkyWalking集成Kafka实现日志异步采集经验总结

SkyWalking日志异步采集架构 【重点知识】 1、【Agent】kafka-reporter-plugin-x.x.x.jar包放plugins目录后必走kafka&#xff08;kafka没有正确配置就会报错&#xff09; 2、【Agent】异步如不开启数据压缩&#xff0c;日志数据较大&#xff0c;pod多、业务大时容易造成网络…

C++第十六讲:红黑树

C第十六讲&#xff1a;红黑树 1.什么是红黑树1.1红黑树的特点 2.MyRBTree实现2.1红黑树的结构2.2红黑树的插入2.2.1插入的总体逻辑2.2.2情况一&#xff1a;变色2.2.3情况二&#xff1a;单旋 变色2.2.4情况三&#xff1a;双旋 变色2.2.4插入代码总结 2.3红黑树的检查2.4完整代…

KubeKey一键安装部署k8s集群和KubeSphere详细教程

目录 一、KubeKey简介 二、k8s集群KubeSphere安装 集群规划 硬件要求 Kubernetes支持版本 操作系统要求 SSH免密登录 配置集群时钟 所有节点安装依赖 安装docker DNS要求 存储要求 下载 KubeKey 验证KubeKey 配置集群文件 安装集群 验证命令 登录页面 一、Ku…

Java 值传递

1 形参&实参 方法的定义可能会用到参数&#xff0c;参数在程序语言中分为&#xff1a; 实参&#xff1a;用于传递给函数/方法的参数&#xff0c;必须有确定的值。 形参&#xff1a;用于定义函数/方法&#xff0c;接收实参&#xff0c;不需要有确定的值。 String hello …

开源一款I2C电机驱动扩展板-FreakStudio多米诺系列

总线直流电机扩展板 原文链接&#xff1a; FreakStudio的博客 摘要 设计了一个I2C电机驱动板&#xff0c;通过I2C接口控制多个电机的转速和方向&#xff0c;支持刹车和减速功能。可连接16个扩展板&#xff0c;具有PWM输出、过流过热保护和可更换电机驱动芯片。支持按键控制…

论文笔记(七十二)Reward Centering(三)

Reward Centering&#xff08;三&#xff09; 文章概括摘要3 基于值的奖励中心化4 案例研究&#xff1a; 以奖励为中心的 Q-learning5 讨论、局限性与未来工作致谢 文章概括 引用&#xff1a; article{naik2024reward,title{Reward Centering},author{Naik, Abhishek and Wan…

内部知识库的核心模块是什么?

内容概要 现代企业内部知识库的架构设计遵循系统性、可扩展性与安全性三重原则&#xff0c;其核心模块的协同运作构成完整的知识资产运营体系。在知识存储层&#xff0c;基于结构化分类的存储管理采用多级目录架构&#xff08;如客户服务库、培训学习库&#xff09;&#xff0…

kafka基本知识

什么是 Kafka&#xff1f; Apache Kafka 是一个开源的分布式流处理平台&#xff0c;最初由 LinkedIn 开发&#xff0c;后来成为 Apache 软件基金会的一部分。Kafka 主要用于构建实时数据管道和流处理应用程序。它能够高效地处理大量的数据流&#xff0c;广泛应用于日志收集、数…

P8716 [蓝桥杯 2020 省 AB2] 回文日期

1 题目说明 2 题目分析 暴力不会超时&#xff0c;O(n)的时间复杂度&#xff0c; < 1 0 8 <10^8 <108。分析见代码&#xff1a; #include<iostream> #include<string> using namespace std;int m[13]{0,31,28,31,30,31,30,31,31,30,31,30,31};// 判断日期…

手机时钟精确到秒

这里以小米手机 MIUI 系统 举例 进入开发者模式 设置 - 我的设备 - 全部参数与信息 快速连续多次点击 MIUI 版本选框&#xff0c;即可进入开发者模式&#xff1b; 打开时间悬浮窗 设置 - 更多设置 - 开发者选项&#xff1b; 滑动至 输入 模块&#xff0c;开启时间悬浮窗&a…

京东广告基于 Apache Doris 的冷热数据分层实践

一、背景介绍 京东广告围绕Apache Doris建设广告数据存储服务&#xff0c;为广告主提供实时广告效果报表和多维数据分析服务。历经多年发展&#xff0c;积累了海量的广告数据&#xff0c;目前系统总数据容量接近1PB&#xff0c;数据行数达到18万亿行&#xff0c;日查询请求量8…

ubuntu新系统使用指南

1. 更新源 2. 配置rime 输入法 sudo apt install ibus-rimeibus-setup #打开配置界面添加雾凇拼音 cd ~/Documents/Tool/input_source/plumgit clone --depth 1 https://github.com/rime/plum plum #没有梯子就劝退cd plum/bash rime-install iDvel/rime-ice:others/recipe…

给小米/红米手机root(工具基本为官方工具)——KernelSU篇

目录 前言准备工作下载刷机包xiaomirom下载刷机包【适用于MIUI和hyperOS】“hyper更新”微信小程序【只适用于hyperOS】 下载KernelSU刷机所需程序和驱动文件 开始刷机设置手机第一种刷机方式【KMI】推荐提取boot或init_boot分区 第二种刷机方式【GKI】不推荐 结语 前言 刷机需…

Liunx(CentOS-6-x86_64)系统安装MySql(5.6.50)

一&#xff1a;安装Liunx&#xff08;CentOS-6-x86_64&#xff09; 安装Liunx&#xff08;CentOS-6-x86_64&#xff09; 二&#xff1a;下载MySql&#xff08;5.6.50&#xff09; MySql下载官网 二&#xff1a;安装MySql 2.1 将mysql上传到Liunx 文件地址 /usr/local/ 2…