【北京迅为】《iTOP-3588开发板系统编程手册》-第20章 socket 应用编程

RK3588是一款低功耗、高性能的处理器,适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用,RK3588支持8K视频编解码,内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP,内置NPU,支持INT4/INT8/INT16/FP16混合运算能力,支持安卓12和、Debian11、Build root、Ubuntu20和22版本登系统。了解更多信息可点击迅为官网   

【粉丝群】824412014

【实验平台】:迅为RK3588开发板

【内容来源】《iTOP-3588开发板系统编程手册》

【全套资料及网盘获取方式】联系淘宝客服加入售后技术支持群内下载

【视频介绍】:【强者之芯】 新一代AIOT高端应用芯片 iTOP -3588人工智能工业AI主板


第20章 socket 应用编程 

20.1 socket介绍

Socket是计算机网络编程中一个重要的概念,它是在应用层和传输层之间提供的一种抽象接口,用于实现应用程序之间的数据交换。Socket允许程序员使用一种通用的接口来访问底层传输协议,如TCP和UDP,以便进行网络通信。

Socket是一种编程接口,它提供了一种标准化的方式来创建网络连接,并允许应用程序在网络上发送和接收数据。Socket API提供了一组函数,这些函数可以用于创建和配置套接字,建立连接,发送和接收数据,以及关闭连接等操作。

在计算机网络中,通常使用两种不同的套接字类型:流套接字和数据报套接字。流套接字提供了面向连接的可靠数据传输,例如TCP协议,而数据报套接字则提供了不可靠的数据传输,例如UDP协议。下面对一些常见的Socket编程相关术语进行介绍:

相关术语

属于介绍

IP地址

唯一标识了网络上的一台主机

端口号

是一个16位数字,用于标识一个应用程序在主机上的具体位置

套接字

用于标识一条网络连接的两端,包含IP地址和端口号

服务器

在网络上提供服务的主机

客户端

与服务器进行通信的主机

Socket编程通常分为两个部分:服务器端和客户端。服务器端监听一个指定的端口,等待客户端连接。一旦客户端连接到服务器端,服务器端将创建一个新的套接字来处理该客户端的请求。服务器可以同时处理多个客户端请求,每个客户端都会有自己的套接字连接。

客户端首先创建一个套接字,然后连接到服务器端的指定IP地址和端口号。一旦连接建立,客户端可以通过套接字发送和接收数据。客户端通常是一次性连接,一旦任务完成就关闭套接字。

Socket编程可以用于各种不同的应用程序,例如聊天程序、文件传输、在线游戏等。Socket编程还可以用于创建网络服务器,提供Web服务、FTP服务、邮件服务等。

20.2 socket编程步骤

socket编程的主要步骤和对应的系统调用如下所示:

步骤

介绍

系统调用

1

创建套接字

socket(domain, type, protocol)

2

绑定套接字

bind(sockfd, addr, addrlen)

3

监听连接

listen(sockfd, backlog)

4

接受连接

accept(sockfd, addr, addrlen)

5

接收和发送数据

recv(sockfd, buf, len, flags)

send(sockfd, buf, len, flags)

6

关闭套接字

close(sockfd)

在本小节将对socket编程的每个步骤进行详细的介绍

20.2.1创建套接字

在Linux socket编程中,创建套接字是构建网络应用程序的第一步。套接字可以理解为应用程序和网络之间的桥梁,用于在网络上进行数据的收发和处理。

在Linux中,可以使用socket系统调用创建套接字。该系统调用的原型和所需头文件如下所示:

所需头文件

函数原型

1

2

#include <sys/types.h>          

#include <sys/socket.h>

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

其中,domain参数指定了套接字的协议族,type参数指定了套接字的类型,protocol参数指定了套接字所使用的具体协议。下面分别介绍这三个参数的含义:

(1)协议族

协议族指定了套接字所使用的协议类型,常用的协议族包括AF_INET、AF_INET6、AF_UNIX等。其中,AF_INET表示IPv4协议族,AF_INET6表示IPv6协议族,AF_UNIX表示Unix域协议族。

(2)套接字类型

套接字类型指定了套接字的数据传输方式,常用的套接字类型包括SOCK_STREAM、SOCK_DGRAM、SOCK_RAW等。其中,SOCK_STREAM表示面向连接的流套接字,主要用于可靠传输数据,例如TCP协议。SOCK_DGRAM表示无连接的数据报套接字,主要用于不可靠传输数据,例如UDP协议。SOCK_RAW表示原始套接字,可以直接访问底层网络协议。

(3)协议类型

协议类型指定了套接字所使用的具体协议类型,常用的协议类型包括IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP等。其中,IPPROTO_TCP表示TCP协议,IPPROTO_UDP表示UDP协议,IPPROTO_ICMP表示ICMP协议,通常使用0表示由系统自动选择适合的协议

例如可以使用以下代码创建一个新的套接字:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

20.2.2绑定套接字

创建套接字后,需要将其与一个网络地址绑定,以便其他计算机可以访问该套接字。在Linux系统下,可以使用bind()系统调用绑定套接字和地址。该系统调用的原型和所需头文件如下所示:

所需头文件

函数原型

1 

2

#include <sys/types.h>          

#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr,

socklen_t addrlen);

其中,sockfd参数指定了需要绑定的套接字描述符,addr参数指定了需要绑定的地址信息,可以是struct sockaddr_in或struct sockaddr_in6等结构体类型,addrlen参数指定了地址信息的长度。使用以下代码将套接字和地址绑定:

//创建一个 sockaddr_in 结构体类型的 servaddr 变量用于存储服务器的地址信息,并将其清零。
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;//指定使用 IPv4 协议(AF_INET)
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//监听本地任意可用的 IP 地址(INADDR_ANY)
servaddr.sin_port = htons(port);//使用指定的端口号(port)。//将套接字 sockfd 绑定到指定的地址 servaddr 上,bind() 函数返回值为0表示绑定成功,
if (bind(sockfd, (struct sockaddr)&servaddr, sizeof(servaddr)) != 0)
{perror("bind");exit(EXIT_FAILURE);
}

其中,servaddr是一个struct sockaddr_in类型的变量,用于存储需要绑定的地址信息,sockaddr_in 结构体的定义如下:

struct sockaddr_in {sa_family_t sin_family; // 地址族in_port_t sin_port; // 端口号struct in_addr sin_addr; // IP 地址char sin_zero[8]; // 填充字符
};

在初始化 sockaddr_in 结构体时,用到了以下函数:

memset():用来将 sockaddr_in 结构体的各个成员变量初始化为 0,这是一个常用的初始化方式。其函数原型如下:

所需头文件

函数原型

1

#include <string.h>

void *memset(void *s, int c, size_t n);

其中,s 参数是需要被初始化的内存区域指针,c 参数是填充字符,n 参数是需要填充的内存字节数。

htonsl()和htons()用于将本机字节序的端口号转换为网络字节序的端口号。其函数原型如下:

所需头文件

函数原型

1

2

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

其中,hostshort 和hostlong参数是本机字节序的端口号,函数返回值是网络字节序的端口号。

20.2.3监听连接

绑定套接字后,需要开始监听连接请求,以便其他网络上的客户端能够与该套接字建立连接。这一步骤通常在服务器端完成。。在Linux系统下,可以使用listen()系统调用监听套接字。该系统调用的原型如下:

所需头文件

函数原型

1

#include <sys/socket.h>

int listen(int socket, int backlog);

其中,sockfd参数指定了需要监听的套接字描述符,backlog参数指定了连接队列的长度,即等待接受的连接数。例如可以使用以下代码开始监听连接

if (listen(sockfd, SOMAXCONN) != 0) 
{perror("listen");exit(EXIT_FAILURE);
}

其中,SOMAXCONN是一个宏定义,指定了连接队列的最大长度。

20.3.4接受连接

当有客户端请求连接时,需要接受该连接并进行处理。在Linux系统下,可以使用accept()系统调用接受连接请求。该系统调用的原型和所需头文件如下所示:

所需头文件

函数原型

1 

2

#include <sys/socket.h>

int accept(int socket, struct sockaddr *restrict address,socklen_t *restrict address_len);

其中,sockfd参数指定了需要接受连接的套接字描述符,addr参数用于存储客户端的地址信息,addrlen参数用于存储地址信息的长度。使用以下代码接受连接请求:

// 定义一个 sockaddr_in 结构体,用于存储客户端的 IP 地址和端口号
struct sockaddr_in cliaddr;// 定义一个 socklen_t 类型的变量 clilen,用于存储客户端地址结构体的长度
socklen_t clilen = sizeof(cliaddr);// 调用 accept() 系统调用,接受客户端的连接请求,并返回一个新的套接字描述符 connfd,
// 用于与客户端进行通信。accept() 函数会阻塞程序,直到有客户端连接到服务器端。
// sockfd 是服务端的监听套接字,cliaddr 是指向 sockaddr_in 结构体的指针,用于存储客户端的地址信息。
// clilen 是客户端地址结构体的长度,accept() 函数会将实际接受到的客户端地址长度存储到该变量中。
int connfd = accept(sockfd, (struct sockaddr*)&cliaddr, &clilen);if (connfd < 0)// 判断 accept() 函数的返回值,判断客户端连接是否失败
{perror("accept");exit(EXIT_FAILURE);
}

20.3.5接收和发送数据

在 Linux socket 编程中,接收和发送数据是套接字编程的核心步骤之一。当套接字绑定并且处于监听状态,已经成功接受了客户端的连接请求后,接下来就是进行数据的收发。下面将详细介绍如何在 Linux 系统中实现接收和发送数据的过程。

接收数据

在接收数据之前,需要先了解数据在网络传输中的一些基本概念。在 TCP 协议中,发送方发送的数据被分割成一个个 TCP 报文段,每个报文段都包含一个 TCP 首部和数据部分。TCP 首部中包含了一些控制信息,如序号、确认号、窗口大小等,用来保证数据的可靠传输。而数据部分则是发送方发送的应用层数据,如 HTTP 报文、FTP 文件等。

在 Linux socket 编程中,接收数据的过程分为两步:先接收 TCP 首部,再接收数据部分。具体步骤如下:

(1)创建一个缓冲区用于接收数据。缓冲区的大小一般为数据部分的大小。

(2)调用 recv() 系统调用接收数据。其函数原型和所需头文件如下:

所需头文件

函数原型

1

#include <sys/socket.h>

ssize_t recv(int socket, void *buffer, size_t length, int flags);

其中,sockfd 参数是需要接收数据的套接字描述符,buf 参数是用于存储接收数据的缓冲区指针,len 参数是需要接收的数据的最大长度,flags 参数是接收标志,通常为 0。函数返回值为实际接收到的字节数,如果返回值为 0,表示对端已经关闭连接。

在调用 recv() 系统调用时,会先接收 TCP 首部,然后再接收数据部分。如果数据部分比较大,可能需要多次调用 recv() 系统调用才能接收完整的数据。因此,需要使用一个循环来不断接收数据,直到接收到全部数据或者出现错误为止。

另外,需要注意的是,recv() 系统调用是一个阻塞调用,即程序会一直等待直到接收到数据或者出现错误才会返回。如果不希望阻塞调用,可以使用非阻塞 I/O 或者多路复用技术,之前的章节已经学习过了,这里不再进行赘述。

  1. 处理接收到的数据。在数据接收完成后,需要对接收到的数据进行处理。具体处理方式根据具体的应用场景而定,如将接收到的数据显示在终端上、将数据写入文件等。

发送数据

发送数据的步骤如下:

(1)定义数据缓冲区:需要定义一个用于存储待发送数据的缓冲区,比如 char buf[MAXLINE]。

(2)将数据拷贝到缓冲区:将需要发送的数据拷贝到缓冲区中,可以使用 strcpy()、memcpy() 等函数进行拷贝操作。

(3)使用 send() 函数发送数据:send() 函数用于向已经建立连接的套接字发送数据,其函数原型如下:

所需头文件

函数原型

1

#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

函数调用成功将返回发送数据的字节数(返回值为非负数),返回-1 表示发送失败。

send()函数参数含义如下所示:

参数名称

参数含义

sockfd

需要发送数据的套接字描述符。

2

buf

待发送数据的缓冲区指针。

3

len

待发送数据的长度。

4

flags

传输标志,通常为 0。

数据接收示例代码如下:

ssize_t n = send(connfd, buf, strlen(buf), 0);
if (n < 0)
{perror("send");exit(EXIT_FAILURE);
}

需要注意的是,send() 函数并不保证一次能够将所有数据都发送出去,如果数据量比较大,可能需要多次调用 send() 函数才能将所有数据发送出去。

(4)判断是否发送完毕:可以通过判断 send() 函数的返回值和待发送数据的长度是否相等来确定是否发送完毕。

示例代码如下:

if (n == strlen(buf))
{printf("Send successfully!\n");
}
else
{printf("Send incomplete!\n");
}

20.3.6关闭套接字

关闭套接字是一个非常重要的步骤。当套接字不再需要使用时,应该立即关闭以释放系统资源和避免资源浪费。,关闭套接字的步骤非常简单,只需要调用 close() 系统调用即可。close() 系统调用的函数原型如下:

int close(int sockfd);

其中,sockfd 参数是需要关闭的套接字描述符。函数返回值为 0 表示成功,返回值为 -1 表示失败。

20.3 socket编程实验

本小节代码在配套资料“iTOP-3588开发板\03_【iTOP-RK3588开发板】指南教程\03_系统编程配套程序\70”目录下,如下图所示:

实验要求:

服务端接收客户端发来的数据,并将发过来的数据以及客户端ip打印出来。

实验步骤:

首先进入到ubuntu的终端界面输入以下命令来创建服务器端程序 demo70_server.c文件,如下图所示:

vim  demo70_server.c

然后向该文件中添加以下内容:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#define PORT 8888
#define BUFFER_SIZE 1024int main()
{int sockfd, connfd;struct sockaddr_in servaddr, cliaddr;socklen_t cliaddr_len = sizeof(cliaddr);char buffer[BUFFER_SIZE];// 创建套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd == -1) {perror("socket"); // 输出错误信息exit(EXIT_FAILURE);}// 绑定地址和端口号memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // INADDR_ANY 表示本机的所有IP地址servaddr.sin_port = htons(PORT); // 绑定端口号if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {perror("bind"); // 输出错误信息exit(EXIT_FAILURE);}// 监听连接if (listen(sockfd, 10) == -1) {perror("listen"); // 输出错误信息exit(EXIT_FAILURE);}printf("Server started.\n");// 接受客户端连接connfd = accept(sockfd, (struct sockaddr *)&cliaddr, &cliaddr_len);if (connfd == -1) {perror("accept"); // 输出错误信息exit(EXIT_FAILURE);}printf("Client connected: %s:%d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); // 输出客户端地址和端口号// 接收数据while (1) {memset(buffer, 0, BUFFER_SIZE); // 清空缓冲区ssize_t numBytes = recv(connfd, buffer, BUFFER_SIZE - 1, 0); // 接收数据if (numBytes == -1) {perror("recv"); // 输出错误信息exit(EXIT_FAILURE);}else if (numBytes == 0) {printf("Client closed connection.\n"); // 客户端关闭连接break;}else {printf("Received from client (%s:%d): %s", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port), buffer); // 输出接收到的数据和客户端地址和端口号}}// 关闭套接字close(connfd);close(sockfd);printf("Server terminated.\n");return 0;
}

保存退出之后,创建客户端程序demo70_server.c,然后向该文件写入以下内容如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#define PORT 8888
#define BUFFER_SIZE 1024int main(int argc, char *argv[])
{int sockfd;struct sockaddr_in servaddr;char buffer[BUFFER_SIZE];// 检查命令行参数个数if (argc < 2) {fprintf(stderr, "Usage: %s server_ip\n", argv[0]); // 打印使用方法exit(EXIT_FAILURE);}// 创建套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd == -1) // 创建套接字失败{perror("socket"); // 打印错误信息exit(EXIT_FAILURE);}// 设置服务端地址和端口号memset(&servaddr, 0, sizeof(servaddr)); // 将地址结构体清零servaddr.sin_family = AF_INET; // 使用IPv4地址servaddr.sin_addr.s_addr = inet_addr(argv[1]); // 从命令行参数中获取服务器IP地址servaddr.sin_port = htons(PORT); // 设置服务器端口号// 连接服务器if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) // 连接失败{perror("connect"); // 打印错误信息exit(EXIT_FAILURE);}// 从终端读入数据并发送给服务器while (fgets(buffer, BUFFER_SIZE, stdin) != NULL) // 从标准输入中读取一行数据{if (send(sockfd, buffer, strlen(buffer), 0) == -1) // 发送消息到服务器{perror("send"); // 打印错误信息exit(EXIT_FAILURE);}}// 关闭套接字close(sockfd);return 0;}

保存退出之后,使用以下命令设置交叉编译器环境,并分别对demo70_server.c和demo70_client.c进行编译和交叉编译,编译完成如下图所示:

export PATH=/usr/local/arm64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin:$PATH

gcc -o demo70_server demo70_server.c

aarch64-none-linux-gnu-gcc -o demo70_client demo70_client.c

然后将交叉编译生成的demo70_client文件拷贝到/home/nfs共享目录下,如下图所示: 

首先启动开发板,Buildroot系统启动之后,首先使用以下命令进行nfs共享目录的挂载(其中192.168.1.7为作者ubuntu的ip地址,需要根据自身ubuntu的ip来设置),如下图所示:

mount -t nfs -o nfsvers=3,nolock 192.168.1.7:/home/nfs /mnt

nfs共享目录挂载到了开发板的/mnt目录下,进入到/mnt目录下,如下图所示: 

可以看到/mnt目录下的demo70_client文件已经存在了,该程序为socket的客户端,首先使用命令“ifconfig”命令查看本机IP如下图所示:

可以看到开发板IP为192.168.1.106,然后在虚拟机ubuntu上使用“ifconfig”命令查看服务端IP,如下所示:

可以看到服务端IP为192.168.1.7,然后在虚拟机ubuntu使用“./demo70_server”命令运行服务端程序,如下图所示:

可以看到该应用会阻塞,等待服务端连接,下面回到开发板终端,使用以下命令运行socket客户端应用程序连接服务端,如下图所示:

./demo70_client 192.168.1.7

 

然后输入要发送的数据,如下图所示:

在虚拟机ubuntu虚拟机运行的服务端代码会接收到相应的数据如下图所示:

至此,我们的socket简单测试就完成了,本小节只是对socket编程进行简单的认识,如果想要更深入的了解socket编程可以在网上寻找专门的书籍或者视频来进行学习。

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

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

相关文章

deep learning

谷歌在线notebook 一、基本数据类型与用法 1.torch.tensor(张量) 按照维度不同(中括号的对数)&#xff0c;可以用torch.tensor创建scalar(标量)、vector(向量)、matrix(矩阵)&#xff0c; 一般的&#xff0c;一维是标量&#xff0c;二维是向量&#xff0c;三维是矩阵&#…

七星创客新零售系统:颠覆性商业模式的崛起

大家好&#xff0c;我是微三云周丽&#xff0c;今天给大家分析当下市场比较火爆的商业模式&#xff01; 小编今天跟大伙们分享什么是七星创客新零售系统&#xff1f; 随着经济的快速发展和科技的不断进步&#xff0c;商业模式的革新成为了企业发展的关键。在这个新旧动能转换、…

sudo的设置

sudo指令就是提高你的用户权限&#xff0c;用来完成root可以完成的工作&#xff0c;但是有一个前提&#xff0c;就是被root添加到信任名单中&#xff0c;接下来我们要讲解如何在root中添加用户到信任名单中。 在root中输入指令&#xff1a; 即可到达添加信用列表的位置&#x…

【漏洞复现】卡车卫星定位系统 /user/create接口处存在未授权密码重置漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

Linux:进程与计划任务

文章目录 Linux&#xff1a;进程与计划任务一、进程1、进程是什么2、进程状态 二、列出进程命令1、查看静态的进程统计信息——“ps”Play1&#xff1a;“ps aux”Play2:ps -elf 2、查看静态的进程统计信息——“top”段首解析进程信息区解释 三、运行与终止进程3.1、运行进程3…

【网络安全】对称加密、非对称加密以及密钥分配

目录 1、对称加密 2、非对称加密 3、如何分配对称密钥&#xff1f; 4、如何分配非对称密钥&#xff1f; 1、对称加密 所谓对称加密&#xff0c;就是指加密密钥与解密密钥都使用相同的密钥。如下图所示&#xff0c;通信双方使用的就是对称加密密钥。//代表&#xff1a;DES和…

军工单位安全内网文件导出,怎样做到严密的安全管控?

军工单位是指承担国家下达的军事装备、产品研制、生产计划任务的企、事业单位&#xff0c;主要包括电子工业部、航空工业总公司、航天工业总公司、兵器工业总公司、核工业总公司、船舶工业总公司、中国工程物理研究院及各省国防工业办公室等。 军工单位的特点主要体现在以下几个…

多目标应用:基于非支配排序粒子群优化算法NSPSO求解无人机三维路径规划(MATLAB代码)

一、无人机多目标优化模型 无人机三维路径规划是无人机在执行任务过程中的非常关键的环节&#xff0c;无人机三维路径规划的主要目的是在满足任务需求和自主飞行约束的基础上&#xff0c;计算出发点和目标点之间的最佳航路。 1.1路径成本 无人机三维路径规划的首要目标是寻找…

学习笔记记录ensp中防火墙配置(trust,unstrus,dmz 资源下载可用)

实验目的&#xff0c;通过配置防火墙控制相互之间的访问&#xff0c;拓扑图如下 资源已上传&#xff0c;注意lsw1和ar2的路由表到各个网段的路由表配置&#xff0c;通过防火墙来控制各个区域能否访问成功。 防火墙通过cloud2链接&#xff0c;方便登录网页配置防火墙策略。防火…

js的算法-交换排序(快速排序)

快速排序 基本思想 快速排序的基本思想是基于分治法的&#xff1a;在待排序表L【1...n】中任意取一个元素p 作为枢轴&#xff08;或基准&#xff0c;通常取首元素&#xff09;。通过一趟排序将待排序表划分为独立的两部分L【1...k-1】和L【k1...n】;这样的话&#xff0c;L【1…

数据结构 第六章 树与二叉树(二)

&#x1f680; 【考纲要求】二叉树的定义及其主要特征&#xff1b;二叉树的顺序存储和链式存储 二、二叉树的概念 1&#xff09;什么是二叉树&#xff1f; 对于二叉树来说&#xff0c;它是一个特殊的树形结构&#xff0c;其每个节点都最多有两个孩子&#xff08;即节点的度最…

Redis入门到通关之Redis数据结构-Hash篇

文章目录 ☃️ 概述☃️底层实现☃️源码☃️其他 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博客 关于博主&#xff1a; 我是 请回答1024&#xff0c;一个追求数学与计算的边界、时间与空间的平衡&#xff0c;0与1的延伸的后…

ESP-IDF下载与安装完整流程

本文主要看参考官网说明&#xff0c;如下&#xff1a; Windows 平台工具链的标准设置 - ESP32 - — ESP-IDF 编程指南 latest 文档 (espressif.com) 一、概述 ESP-IDF需要安装一些必备工具&#xff0c;才能围绕ESP32构建固件&#xff0c;包括&#xff1a; PythonGit交叉编译…

圈子交友系统话题设置-免费圈子社区论坛交友系统-圈子交友系统功能介绍-APP小程序H5多端源码交付!

1. 圈子的独特创造与精心管理 源码赋予用户创造独特圈子的能力&#xff0c;为志同道合的人们打造一个分享兴趣、交流见解的平台。每个圈子都可以个性化定制主题、标签和规则&#xff0c;以确保圈子具备个性特点和强烈的社群感。作为圈子的创建者&#xff0c;您将享有自由编辑资…

LabVIEW专栏八、类

该章目的是可以开发仪器类。 一、类的概述 一般来说类有三大特性&#xff0c;封装&#xff0c;继承和多态。 在实际项目中&#xff0c;最主要是继承和多态&#xff0c;要搞清楚这两者的概念和在LabVIEW中是怎样应用的。在LabVIEW中&#xff0c;面向对象编程用到的就是LabVIE…

基于高斯混合模型的视频背景提取和人员跟踪算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2013B 3.部分核心程序 .............................................................................. %我们这里…

利用大模型与AI Agent,实现企业数据智能分析

导语&#xff1a;大模型爆火之后&#xff0c;很多企业也用大模型做了相关探索和实践&#xff0c;我们发现大模型解决单点问题时效果更好。但同时会产生安全、幻想等相关问题。今天从传统数据分析的痛点&#xff0c;到大模型智能分析的建设方式&#xff0c;并结合相关实践案例&a…

OpenHarmony实战开发-合理运行后台任务

简介 设备返回主界面、锁屏、应用切换等操作会使应用退至后台。为了降低设备耗电速度、保障用户使用流畅度&#xff0c;系统会对退至后台的应用进行管控&#xff0c;包括进程挂起和进程终止。为了保障后台音乐播放、日历提醒等功能的正常使用&#xff0c;系统提供了受规范约束…

安全AI未来 | C3安全大会 · 2024,数据驱动 AI原生

数字为时代变革注入动力&#xff0c;AI为重塑社会文明带来原力。数智浪潮中&#xff0c;我们见证着时代跃迁的巨变&#xff0c;面临着适变、应变、驭变的挑战。 数字驱动、AI原生。数字的流动不仅承载着信息&#xff0c;更将激活未来的无限价值&#xff1b;AI&#xff0c;不…

unity cinemachine相机 (案例 跟随角色移动)

安装相机包 打开包管理工具 在 unity registry 搜索cinemachine 会在maincamera中生成一个组件cinemachineBrain 只能通过虚拟相机操控 主相机 虚拟相机的参数 案例 1.固定相机效果 位置 在固定的地方 默认的模式 2.相机跟随人物效果 焦距设置 20 跟随设置 把playere…