【北京迅为】《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://www.mzph.cn/bicheng/2273.shtml

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

相关文章

TI_DSP_F2808学习笔记1: GPIO

1. 初始化设置 1.1 控制寄存器 GPxMUX功能选择寄存器/多功能复用选择 GPxDIR 方向选择寄存器/输入输出选择 0 输入 1 输出GPxPUD 上拉功能选择寄存器/是否启用内部上拉 0 有上拉&#xff0c;1禁止上拉GPxQSeln输入限定选择寄存器 输入n次为0或1才有效&#xff0c;滤波 1.2 数…

PDF 书签制作与调整

本文是对以前发表的旧文拆分&#xff0c;因为原文主题太多&#xff0c;过长&#xff0c;特另起一篇分述。 第一部分 由可编辑 PDF 文档创建书签 方法 1. Adobe Acrobat Pro autobookmark AutoBookmark 是一个可用于 Adobe Acrobat 自动生成书签的插件。 官方下载地址&…

corona渲染器锐化模糊设置,corona高效出图方法

​在使用Corona渲染器进行效果图渲染时&#xff0c;锐化和模糊是两种常用的设置&#xff0c;它们主要用于调整图像的清晰度和柔化效果。锐化参数可以增强图像中的细节&#xff0c;使画面看起来更加清晰锋利&#xff1b;而模糊参数则可以用来柔化图像边缘&#xff0c;减少图像噪…

Etsy多账号关联怎么办?Etsy店铺防关联解决方法

Etsy虽然相对于其他跨境电商平台来说比较小众&#xff0c;但因为平台是以卖手工艺品为主的&#xff0c;所以成本较低&#xff0c;利润很高。许多跨境卖家都纷纷入驻&#xff0c;导致平台规则越发严格&#xff0c;操作不当就会封号&#xff0c;比如一个卖家操作多个账号会出现关…

10.接口自动化测试学习-Pytest框架(2)

1.mark标签 如果在每一个模块&#xff0c;每一个类&#xff0c;每一个方法和用例之前都加上mark标签&#xff0c;那么在pytest运行时就可以只运行带有该mark标签的模块、类、接口。 这样可以方便我们执行自动化时&#xff0c;自主选择执行全部用例、某个模块用例、某个流程用…

二分查找知识点及练习题

知识点讲解 一、没有相同元素查找 请在一个有序递增数组中&#xff08;不存在相同元素&#xff09;&#xff0c;采用二分查找&#xff0c;找出值x的位置&#xff0c;如果x在数组中不存在&#xff0c;请输出-1&#xff01; 输入格式 第一行&#xff0c;一个整数n&#xff0c;代…

家用洗地机买什么牌子的好?四大业内顶尖品牌推荐

家庭清洁一直是必不可少的&#xff0c;但用传统的手动拖地清洁&#xff0c;费时又费力。现在出现了洗地机&#xff0c;确实改变了我们对家庭清洁的看法。它不仅能扫地、拖地&#xff0c;还能吸水&#xff0c;甚至能够自动清洁滚刷解放我们双手&#xff0c;提供高效清洁的同时还…

【Linux系列】 离线安装vnc 可视化桌面

离线安装vnc 可视化桌面 缘下载安装vnc初始化链接 缘 项目需要下载 下载地址&#xff1a; http://mirror.centos.org/centos/7/updates/x86_64/Packages/tigervnc-license-1.8.0-31.el7_9.noarch.rpm http://mirror.centos.org/centos/7/os/x86_64/Packages/libXfont2-2.0.…

【Day 6】MySQL 基础

1 MySQL DataBase&#xff08;DB&#xff09;是存储和管理数据的仓库 DataBaseManagementSystem&#xff08;DBMS&#xff09;数据库管理系统&#xff0c;操纵和管理数据库的大型软件 SOL&#xff08;Structured QueryLanguage&#xff09;操作关系型数据库的编程语言&#…

C++/Qt 小知识记录5

工作中遇到的一些小问题&#xff0c;总结的小知识记录&#xff1a;C/Qt 小知识5 Windows下查看端口占用情况C调用Python三方库测试库有没有被加上的测试方法初始化使用Python的env环境&#xff0c;用Py_SetPythonHome设置GDAL相关的&#xff0c;需要把osgeo、rasterio的路径加入…

【iOS开发】(一)2024 从一无所有开始,到ios开发(react Native)

​ 2024 从一无所有开始&#xff0c;到ios开发&#xff08;react Native&#xff09; 目录标题 1 工具简介2 基础环境搭建1 安装 brew2 安装 Node.js3 安装 Yarn4 安装 React Native 脚手架 3 ios环境搭建4创建并启动一个app 在这里插入图片描述 1 工具简介 Homebrew (brew)&a…

OpenHarmony实战开发-页面布局检查器ArkUI Inspector使用指导

DevEco Studio内置ArkUI Inspector工具&#xff0c;开发者可以使用ArkUI Inspector&#xff0c;在DevEco Studio上查看应用在真机上的UI显示效果。利用ArkUI Inspector工具&#xff0c;开发者可以快速定位布局问题或其他UI相关问题&#xff0c;同时也可以观察和了解不同组件之间…

Matlab分段微分方程组拟合【案例源码+视频教程】

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《复杂函数拟合案例分享》本专栏旨在提供 1.以案例的形式讲解各类复杂函数拟合的程序实现方法&#xff0c;并提供所有案例完整源码&#xff1b;2.…

LLM 构建Data Multi-Agents 赋能数据分析平台的实践之③:数据分析之一(智能报表)

概述 在企业数字化转型的过程中&#xff0c;ERP系统与数据平台作为核心支撑工具&#xff0c;对于提升运营效率、优化决策支持、实现业务流程一体化起着至关重要的作用。然而&#xff0c;智能报表与报表的智能化合并作为其中的重要领域&#xff0c;却往往面临诸多挑战与难点&am…

探索 去中心化的Web3.0

随着区块链技术的日益成熟和普及&#xff0c;Web3&#xff08;Web 3.0&#xff09;已经成为一个无法忽视的趋势。Web3不仅仅是一个技术概念&#xff0c;更是一个去中心化、透明、用户数据拥有权归还给用户的互联网新时代。在这篇文章中&#xff0c;我们将深入探讨Web3技术的核心…

纯js图片上传插件

目录标题 一、效果预览二、使用简单三、完整代码&#xff08;一&#xff09;index.html&#xff08;二&#xff09;css&#xff08;三&#xff09;js四、附带后台上传文件代码 一、效果预览 支持多图片上传&#xff0c;删除、预览。 二、使用简单 导入依赖&#xff08;需要…

Dart基础语法

Hello Dart Dart 语言与其他许多编程语言一样&#xff0c;以 main 函数作为程序的入口点。以下是一个简单的 "Hello Dart" 程序示例&#xff0c;展示了 Dart 语言的这一特点。 // 标准写法 void main(){print("Hello Dart"); }// 省略写法 main(){print(&…

WebGL绘制和变换三角形

1、绘制多个点 构建三维模型的基本单位是三角形。不管三维模型的形状多么复杂&#xff0c;其基本组成部分都是三角形&#xff0c;只不过复杂的模型由更多的三角形构成而已。 gl.vertexAttrib3f()一次只能向顶点着色器传入一个顶点&#xff0c;而绘制三角形、矩形和立方体等&am…

【网络安全】HTTP协议 — 特点

专栏文章索引&#xff1a;网络安全 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 学习目标​ 一、请求与响应 1.服务器和客户端 二、不保存状态 1.不保存状态的协议 三、资源定位 1.URI&#xff08;统一资源标识符&#xff09; 四、请求方法 1.请求方法 五…

如何在window系统中安装Mysql

先简单来说说MySQL是什么&#xff1f; MySQL 是最流行的关系型数据库管理系统&#xff0c;在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System&#xff1a;关系数据库管理系统)应用软件之一。 MySQL 由瑞典 MySQL AB 公司开发&#xff0c;目前属于…