嵌入式Linux学习笔记(7)-Socket网络编程

一、什么是Socket网络编程

        Socket是一种抽象的编程接口,可以用于在不同主机之间进行数据通信。Socket API提供了一系列函数来创建、连接、发送和接收数据等操作。嵌入式 Linux 系统中的 Socket 网络编程是指在嵌入式系统中使用 Socket API 进行网络通信。

        Socket 网络编程可以实现各种网络通信功能,如 TCP/IP 通信和 UDP 通信。

二、TCP 与 UDP

        TCP是一种面向连接的协议,它提供可靠的数据传输。它通过建立一个连接,将数据分为多个小的数据包,并保证它们按顺序传输到目标节点。如果有数据包丢失或损坏,TCP会进行重传,确保所有数据包都被传输,并且按顺序重新组装。TCP还提供了流量控制和拥塞控制的机制,以确保网络稳定和高效。 TCP适用于需要可靠传输、顺序传输和流量控制的应用程序,如网页浏览、文件传输和电子邮件等。

        UDP是一种无连接的协议,它提供不可靠的数据传输。UDP将数据分成小的数据包,并将它们发送到目标节点,但不保证它们按顺序送达。UDP不进行重传,也不提供流量控制和拥塞控制。因此,UDP的传输速度相对较快,但在不可靠的网络环境下可能会有数据丢失或乱序。UDP适用于对实时性要求较高,但对数据可靠性要求不高的应用程序,如视频流传输、语音通话和在线游戏等。

TCP/IP通信流程:

        TCP/IP通信通过三次握手建立连接,四次挥手关闭连接

    1. 客户端向服务器发起连接请求,使用传输控制协议(TCP)的三次握手握手建立连接。

    2. 服务器接收到连接请求后,回复一个确认信息给客户端,进行第二次握手。

    3. 客户端接收到确认信息后,再次向服务器发送一个确认信息,进行第三次握手。

    4. 服务器接收到确认信息后,连接建立成功,开始进行数据传输。

    5. 客户端将需要传输的数据分成较小的数据包,并为每个数据包分配一个序列号,并将数据包传输给服务器。

    6. 服务器接收到数据包后,发送一个确认信息给客户端,表示已经接收到数据。

    7. 客户端接收到确认信息后,再次向服务器发送下一个数据包。

    8. 服务器不断接收和发送数据包,直到所有数据传输完成。

    9. 数据传输完成后,客户端发送一个连接释放请求给服务器,并等待服务器回复,进行第一次挥手。

    10. 服务器接收到连接释放请求后,发送一个确认信息给客户端,表示同意释放连接,进行第二次挥手。

    11. 客户端接收到确认信息后,不可以再向服务端发送消息,但仍可以接收服务端发送的消息。

    12. 服务端如果没有要发送的消息,此时发送一个连接释放请求给客户端,并等待客户端回复,进行第三次挥手。

    13. 客户端接收到连接释放请求后,发送一个确认信息给服务端,表示同意释放连接,进行第四次挥手。此时客户端关闭。

    14. 服务端接收到确认信息后关闭。

UDP通信流程:

        UDP通信不需要建立连接和释放连接

    1. 客户端将需要传输的数据打包成数据报,并指定目标主机的IP地址和端口号。

    2. 客户端将数据报发送给目标主机。

    3. 服务器接收到数据报后,根据目标端口号对数据进行处理。

    4. 服务器根据需要向客户端发送响应数据报。

    5. 客户端接收到服务器的响应数据报后,进行相应的处理。

    6. 数据传输完成后,连接自动关闭,不需要进行连接释放。

三、相关函数

        在C语言中提供了一系列的函数来创建、连接、发送和接收网络数据。下面是一些常见的Socket网络编程相关函数和它们的用法:

1、TCP 相关函数

        socket()函数:创建一个新的Socket,并返回一个文件描述符。它接受三个参数:地址域(AF_INET表示IPv4)、类型(SOCK_STREAM表示TCP)和协议(0表示根据类型自动选择协议)。示例用法:

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

        bind()函数:将Socket绑定到一个特定的本地地址和端口。它接受三个参数:Socket文件描述符、指向本地地址结构的指针和本地地址结构的大小。示例用法:

struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;
bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));

        listen()函数:将Socket设置为监听状态,等待连接请求。它接受两个参数:Socket文件描述符和最大连接数。示例用法:

listen(sockfd, BACKLOG);

        accept()函数:接受客户端的连接请求,并返回一个新的Socket文件描述符,用于后续的数据传输。它接受三个参数:Socket文件描述符、指向客户端地址结构的指针和客户端地址结构的大小。示例用法:

int new_sockfd;
new_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);

        connect()函数:与远程服务器建立连接。它接受三个参数:Socket文件描述符、指向远程地址结构的指针和远程地址结构的大小。示例用法:

struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
inet_pton(AF_INET, "127.0.0.1", &(serv_addr.sin_addr));
connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

        send()函数:发送数据到连接的Socket。它接受四个参数:Socket文件描述符、指向数据的指针、数据的大小和附加参数。示例用法:

char message[] = "Hello, World!";
send(sockfd, message, strlen(message), 0);

        recv()函数:从连接的Socket接收数据。它接受四个参数:Socket文件描述符、指向接收缓冲区的指针、缓冲区的大小和附加参数。示例用法:

char buffer[MAX_BUFFER_SIZE];
int bytes_received = recv(sockfd, buffer, MAX_BUFFER_SIZE - 1, 0);

        close()函数:关闭Socket连接。它接受一个参数:Socket文件描述符。示例用法:

close(sockfd);

2、UDP相关函数

        UDP 其余函数与 TCP 相同,只是发送和接收函数略有不同。

        sendto()函数:向指定的目标地址发送数据。它接受六个参数:套接字文件描述符、数据缓冲区、数据大小、附加参数(通常为0)、目标地址结构的指针和目标地址结构的大小。

char message[] = "Hello, World!";
struct sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
client_addr.sin_port = htons(PORT);sendto(sockfd, message, strlen(message), 0, (struct sockaddr*)&client_addr, sizeof(client_addr));

        recvfrom()函数:从指定的源地址接收数据。它接受六个参数:套接字文件描述符、接收缓冲区、缓冲区大小、附加参数(通常为0)、源地址结构的指针和源地址结构的大小。

char buffer[1024];
struct sockaddr_in client_addr;
int addr_len = sizeof(client_addr);recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&client_addr, &addr_len);

        注意:UDP是无连接的,所以在发送数据时不需要先建立连接。发送数据时,可以指定目标地址,也可以不指定(这时可以直接使用send()函数)。接收数据时,可以获取到数据的源地址。

四、基于TCP的Socket通信

1、通信流程

服务器端(server)的流程大致如下:

  1. 创建Socket:使用socket()函数创建一个Socket,并指定协议族和Socket类型。

  2. 绑定Socket:使用bind()函数将Socket与特定的IP地址和端口号绑定。

  3. 监听连接:使用listen()函数将Socket设置为监听状态。

  4. 接受连接:使用accept()函数接受客户端的连接请求,并创建一个新的Socket用于与客户端通信。

  5. 与客户端通信:使用send()函数向客户端发送数据,使用recv()函数从客户端接收数据。

  6. 关闭连接:使用close()函数关闭Socket连接。

客户端(client)的流程大致如下:

  1. 创建Socket:使用socket()函数创建一个Socket,并指定协议族和Socket类型。

  2. 连接服务器:使用connect()函数与服务器建立连接。

  3. 与服务器通信:使用send()函数向服务器发送数据,使用recv()函数从服务器接收数据。

  4. 关闭连接:使用close()函数关闭Socket连接。

 2、编写实例

        server.c

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>#include <unistd.h>
#define handle_error(cmd, result) \if (result < 0)               \{                             \perror(cmd);              \return -1;                \}void *read_from_client(void *argv){// 使用recv接收客户端发送的数据打印到控制台char *read_buf = NULL;int client_fd = *(int *)argv;read_buf = malloc(sizeof(char*) * 1024);ssize_t count = 0;if (!read_buf){perror("malloc server read_buf");return NULL;}//接收数据  只要能接收到数据 一直挂起while(count = recv(client_fd,read_buf,1024,0)){if (count < 0){perror("malloc server read_buf");return NULL;}fputs(read_buf,stdout);}printf("客户端请求关闭\n");free(read_buf);return NULL;}void *write_from_client(void *argv){// 接受控制台输入的消息 发送出去char *write_buf = NULL;int client_fd = *(int *)argv;write_buf = malloc(sizeof(char*) * 1024);ssize_t count = 0;if (!write_buf){perror("malloc server write_buf");return NULL;}while(fgets(write_buf,1024,stdin) != NULL){//发送数据count = send(client_fd,write_buf,1024,0);if (count < 0){perror("send");return NULL;}}printf("接收到关闭请求,不再写入,关闭连接\n");// 可以具体关闭某一端shutdown(client_fd,SHUT_WR);free(write_buf);return NULL;}int main(int argc, char const *argv[])
{int sockfd,clientfd,temp_result;pthread_t pid_read,pid_write;// 创建服务器地址和客户端地址struct sockaddr_in server_addr,client_addr;// 清空memset(&server_addr,0,sizeof(server_addr));memset(&client_addr,0,sizeof(client_addr));// 填写服务端地址server_addr.sin_family = AF_INET;//协议// 填写ip地址 0.0.0.0server_addr.sin_addr.s_addr = htonl(INADDR_ANY);// inet_pton(AF_INET,"0.0.0.0",&server_addr.sin_addr);// 填写端口号server_addr.sin_port = htons(6666);// 网络编程流程// 1. socketsockfd = socket(AF_INET,SOCK_STREAM,0);//IPV4,TCPhandle_error("socket",sockfd);// 2. 绑定地址temp_result = bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));handle_error("bind",temp_result);// 3. 进入监听状态temp_result = listen(sockfd,128);handle_error("listen",temp_result);// 4. 获取客户端连接socklen_t client_addr_len = sizeof(client_addr);// 返回的 clienfd 才是能够和客户端收发消息的文件描述符clientfd = accept(sockfd,(struct sockaddr *)&client_addr,&client_addr_len);// 如果没有客户端连接会挂起等待handle_error("accpet",clientfd);printf("与客户端%s %d 建立连接,文件描述符是 %d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),clientfd);// 创建线程用于收消息pthread_create(&pid_read,NULL,read_from_client,(void *)&clientfd);// 创建线程用于发消息pthread_create(&pid_write,NULL,write_from_client,(void *)&clientfd);// 阻塞主线程pthread_join(pid_read,NULL);pthread_join(pid_write,NULL);// 释放资源printf("释放资源\n");close(clientfd);close(sockfd);return 0;
}

        client.c

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>#include <unistd.h>
#define handle_error(cmd, result) \if (result < 0)               \{                             \perror(cmd);              \return -1;                \}void *read_from_server(void *argv){// 使用recv接收客户端发送的数据打印到控制台char *read_buf = NULL;int client_fd = *(int *)argv;read_buf = malloc(sizeof(char*) * 1024);ssize_t count = 0;if (!read_buf){perror("malloc server read_buf");return NULL;}//接收数据  只要能接收到数据 一直挂起while(count = recv(client_fd,read_buf,1024,0)){if (count < 0){perror("malloc server read_buf");return NULL;}fputs(read_buf,stdout);}printf("服务端请求关闭\n");free(read_buf);return NULL;}void *write_from_server(void *argv){// 接受控制台输入的消息 发送出去char *write_buf = NULL;int client_fd = *(int *)argv;write_buf = malloc(sizeof(char*) * 1024);ssize_t count = 0;if (!write_buf){perror("malloc server write_buf");return NULL;}while(fgets(write_buf,1024,stdin) != NULL){//发送数据count = send(client_fd,write_buf,1024,0);if (count < 0){perror("send");return NULL;}}printf("接收到关闭请求,不再写入,关闭连接\n");// 可以具体关闭某一端shutdown(client_fd,SHUT_WR);free(write_buf);return NULL;}int main(int argc, char const *argv[])
{int sockfd,temp_result;pthread_t pid_read,pid_write;// 创建服务器地址和客户端地址struct sockaddr_in server_addr,client_addr;// 清空memset(&server_addr,0,sizeof(server_addr));memset(&client_addr,0,sizeof(client_addr));// 填写客户端地址client_addr.sin_family = AF_INET;//协议// 填写ip地址 192.168.1.195inet_pton(AF_INET,"192.168.1.195",&client_addr.sin_addr);// 填写端口号client_addr.sin_port = htons(8888);// 填写服务端地址server_addr.sin_family = AF_INET;//协议// 填写ip地址 0.0.0.0/127.0.0.1inet_pton(AF_INET,"0.0.0.0",&server_addr.sin_addr);// 填写端口号server_addr.sin_port = htons(6666);// 客户端网络编程流程// 1. 创建socketsockfd = socket(AF_INET,SOCK_STREAM,0);handle_error("socket",sockfd);// 2. 绑定temp_result = bind(sockfd,(struct sockaddr *)&client_addr,sizeof(client_addr));handle_error("bind",temp_result);// 3. 主动连接服务端temp_result = connect(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));handle_error("connect",temp_result);printf("连接上服务器%s %d\n",inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port));// 创建线程用于收消息pthread_create(&pid_read,NULL,read_from_server,(void *)&sockfd);// 创建线程用于发消息pthread_create(&pid_write,NULL,write_from_server,(void *)&sockfd);// 阻塞主线程pthread_join(pid_read,NULL);pthread_join(pid_write,NULL);// 释放资源printf("释放资源\n");close(sockfd);return 0;
}

五、基于UDP的Socket通信

1、通信流程

客户端(client)的流程大致如下:

        创建Socket:使用socket()函数创建一个Socket,并指定协议族和Socket类型。

        发送数据:使用sendto()函数将要发送的数据以及服务器的IP地址和端口号发送给服务器。

        接收数据:使用recvfrom()函数从服务器接收数据。

        关闭Socket:使用close()函数关闭Socket连接。

服务器端(server)的流程大致如下:

        创建Socket:使用socket()函数创建一个Socket,并指定协议族和Socket类型。

        绑定Socket:使用bind()函数将Socket与特定的IP地址和端口号绑定。

        接收数据:使用recvfrom()函数从客户端接收数据。

        处理数据:服务器对接收到的数据进行处理,可以根据需要进行相应的操作。

        发送数据:使用sendto()函数将处理后的数据发送给客户端。

        关闭Socket:使用close()函数关闭Socket连接。

2、编写实例

        server.c

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>#define handle_error(cmd, result) \if (result < 0)               \{                             \perror(cmd);              \return -1;                \}int main(int argc, char const *argv[])
{// 使用UDP协议完成客户端与服务端的通信// EOF作为关闭的信号int sockfd,temp_result;char *buf = malloc(sizeof(char) * 1024);// 创建服务器地址和客户端地址struct sockaddr_in server_addr,client_addr;// 清空memset(&server_addr,0,sizeof(server_addr));memset(&client_addr,0,sizeof(client_addr));// 填写服务端地址server_addr.sin_family = AF_INET;//协议// 填写ip地址 0.0.0.0server_addr.sin_addr.s_addr = htonl(INADDR_ANY);// inet_pton(AF_INET,"0.0.0.0",&server_addr.sin_addr);// 填写端口号server_addr.sin_port = htons(6666);// UDP编程流程// 1. socketsockfd = socket(AF_INET,SOCK_DGRAM,0);//IPV4,TCPhandle_error("socket",sockfd);// 2. 服务端绑定地址socklen_t server_len = sizeof(server_addr);socklen_t client_len = sizeof(client_addr);temp_result = bind(sockfd,(struct sockaddr *)&server_addr,server_len);handle_error("bind",temp_result);// 直接收发数据do{// 接收数据存到缓冲memset(buf,0,1024);temp_result = recvfrom(sockfd,buf,1024,0,(struct sockaddr*)&client_addr,&client_len);handle_error("recvfrom",temp_result);if (strncmp(buf,"EOF",3) != 0){printf("接收到客户端%s %d信息: %s\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),buf);strcpy(buf,"OK");}else{printf("准备关闭\n");}temp_result = sendto(sockfd,buf,4,0,(struct sockaddr*)&client_addr,client_len);handle_error("sendto",temp_result);} while (strncmp(buf,"EOF",3) != 0);free(buf);return 0;
}

        client.c

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>#define handle_error(cmd, result) \if (result < 0)               \{                             \perror(cmd);              \return -1;                \}int main(int argc, char const *argv[])
{// 使用UDP协议完成客户端与服务端的通信// EOF作为关闭的信号int sockfd,temp_result;char *buf = malloc(sizeof(char) * 1024);// 创建服务器地址和客户端地址struct sockaddr_in server_addr,client_addr;// 清空memset(&server_addr,0,sizeof(server_addr));memset(&client_addr,0,sizeof(client_addr));// 填写服务端地址server_addr.sin_family = AF_INET;//协议// 填写ip地址 0.0.0.0server_addr.sin_addr.s_addr = htonl(INADDR_ANY);// inet_pton(AF_INET,"0.0.0.0",&server_addr.sin_addr);// 填写端口号server_addr.sin_port = htons(6666);// UDP编程流程// 1. socketsockfd = socket(AF_INET,SOCK_DGRAM,0);//IPV4,TCPhandle_error("socket",sockfd);// 2. 客户端不需要绑定地址socklen_t server_len = sizeof(server_addr);socklen_t client_len = sizeof(client_addr);// temp_result = bind(sockfd,(struct sockaddr *)&server_addr,server_len);// handle_error("bind",temp_result);// 直接收发数据do{write(STDOUT_FILENO,"Type something you want to send: ", 34);// 从控制台读取信息int buf_len = read(STDIN_FILENO,buf,1023);sendto(sockfd,buf,buf_len,0,(struct sockaddr *)&server_addr,server_len);handle_error("sendto",buf_len);// 清空缓冲区memset(buf,0,1024);temp_result = recvfrom(sockfd,buf,1024,0,NULL,NULL);handle_error("recvfrom",temp_result);if (strncmp(buf,"EOF",3) != 0){printf("接收到服务端%s %d返回的数据: %s\n",inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port),buf);}} while (strncmp(buf,"EOF",3) != 0);free(buf);return 0;
}

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

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

相关文章

如何处理不支持网络过滤的CAN收发器失能问题

在最近的CAN网络管理开发过程中&#xff0c;我们遇到了一些具有挑战性的问题。 客户要求我们的系统支持CAN网络管理功能&#xff0c;特别是需要使用ID范围在0X400至0X4FF之间的任意CAN报文来唤醒硬件。为了降低成本&#xff0c;我们选择了恩智浦的TJA1043T作为CAN收发器。然而…

MySQL慢查询优化指南

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 前言 当遇到慢查询问题时&#xff0c;不仅影响服务效率&#xff0c;还可能成为系统瓶颈。作为一位软件工程师&#xff0c;掌握MySQL慢查询优化技巧至关重要。今天&#xff0c;我们就来一场“数据库加速之旅…

Vue:默认插槽

目录 一.性质 1.内容分发 2.无名称标识 3.作用域 4.使用方式 二.使用 1.父组件 2.子组件 三.代码 1.父组件代码 2.子组件代码 四.效果 一.性质 1.内容分发 默认插槽允许组件的使用者定义一些内容&#xff0c;这些内容会被插入到组件模板中的特定位置。这有助于实…

Python画笔案例-059 绘制甩曲彩点动图

1、绘制甩曲彩点动图 通过 python 的turtle 库绘制 甩曲彩点动图,如下图: 2、实现代码 绘制甩曲彩点动图,以下为实现代码: """甩曲彩点动图.py """ import time import turtlecs = [red,orange,

【既约分数 / B】

问题 代码 #include <bits/stdc.h> using namespace std; int main() {int cnt 0;for (int i 1; i < 2020; i){for (int j 1; j < 2020; j){if (__gcd(i, j) 1)cnt;}}cout << cnt; }

k8s介绍-搭建k8s

官网&#xff1a;https://kubernetes.io/ 应用部署方式演变 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其他技术的参与 缺点&#xff1a;不能为应用程序定义资源使用边界&#xff0c;很难合理地分配计…

docker镜像的打包、复制、加载

一、镜像打包 docker save -o /root/ollama.tar ollama/ollama 二、复制 如果网络互通&#xff0c;则可以直接远程复制即可。如果网络不通&#xff0c;则可以先下载到本地再上传到目标主机。这里我直接远程复制&#xff1a; 将本机的ollama.tar文件复制到目标主机192.168.1.2…

【Godot4.3】三角形类

概述 在GDSCript中你想要表示一个平面三角形&#xff0c;只需要设定3个点的位置&#xff0c;也就是3个Vector2就行了&#xff0c;或者一个size()3的PackedVector2Array。 但是想要进一步处理三角形&#xff0c;获得它的一些几何特征&#xff0c;比如&#xff1a;某个内角的角…

HOJ网站开启https访问 申请免费SSL证书 部署证书详细操作指南

https://console.cloud.tencent.com/ 腾讯云用户 登录控制台 右上角搜SSL 点击 SSL证书 进入链接 点申请 免费证书 有效期3个月 &#xff08;以后每三个月申请一次证书 上传&#xff09; 如果是腾讯云申请的域名 选 自动DNS验证 自动添加验证记录 如果是其他平台申请域…

【WPF】03 动态生成控件

说明 今天记录一篇关于动态生成控件的方法&#xff0c;也是反复查了一些资料&#xff0c;逐步完善成自己需要的方法&#xff0c;感觉还是比较好用的。通过这个需求&#xff0c;在网上也找了一些资料&#xff0c;发现了一个开源图形UI组件HandyControl&#xff0c;觉得比较好&a…

【C++ 11多线程加速计算实操教程】

【C 11多线程加速计算实操教程】 1. 了解线程的基本概念2. 创建线程2.1 启动线程的基本示例&#xff1a;2.2 运行结果 3. 线程加速计算3.1 演示如何使用多个线程计算数组的和&#xff1a;3.2 运行结果3.3 结果分析3.4 拓展学习 4. 互斥量&#xff08;Mutex&#xff09;4.1 演示…

【GUI设计】基于图像边缘提取的GUI系统(5),matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于图像边缘提取的GUI系统&#xff08;5&#xff09;&#xff0c;用matlab实现。 本…

HTML、CSS

初识web前端 web标准 Web标准也称为网页标准&#xff0c;由一系列的标准组成&#xff0c;大部分由W3C (World Wide Web Consortium&#xff0c;万维网联盟) 负责制定。三个组成部分: HTML: 负责网页的结构(页面元素和内容)。CSS: 负责网页的表现(页面元素的外观、位置等页面样…

荣耀手机AI搜索革新体验:一键总结归纳,让信息获取更高效

在信息爆炸的时代&#xff0c;我们每天都被海量的数据包围&#xff0c;如何快速、准确地获取所需信息成为了现代人的一大挑战。 近日&#xff0c;荣耀手机宣布其AI搜索功能正式上线&#xff0c;这一创新举措不仅为使用者带来了前所未有的便捷体验&#xff0c;更在智能手机领域…

博图软件项目创建

目录 一、新建项目 二、IP设置具体的版本号查看方法 ​三、电脑IP设置如下 一、新建项目 1、双击打开软件 2、创建新项目&#xff0c;路径可以自己选择&#xff0c;填写相关信息&#xff0c;点击创建 3、选择组态设备 4、选择对应的的设备型号&#xff0c;点击添加 5、密…

【刷题2—滑动窗口】最大连续1的个数lll、将x减到0的最小操作数

目录 一、最大连续1的个数lll二、将x减到0的最小操作数 一、最大连续1的个数lll 题目&#xff1a; 思路&#xff1a; 问题转换为&#xff1a;找到一个最长子数组&#xff0c;这个数组里面0的个数不能超过k个 定义一个变量count&#xff0c;来记录0的个数&#xff0c;进窗口、…

Minio上传url资源文件,文件内容不全的问题

遇到问题 使用minio-client时候上传文件为url链接时候&#xff0c;上传inputstream流出现了文件上传成功&#xff0c;但是文件内容缺失&#xff0c;无法正常打开&#xff01; 先看看基本的依赖和配置代码&#xff1a; pom.xml依赖 <!-- tika MIME检测机制 --><depen…

JVM(HotSpot):程序计数器(Program Counter Register)

文章目录 一、内存结构图二、案例解读三、工作流程四、特点 一、内存结构图 二、案例解读 我们使用javap对字节码进行反编译&#xff0c;来看下程序计数器怎么体现的。 IDEA写一个简单的Java代码 反编译命令 javap -verbose InitTest.class $ javap -verbose InitTest.clas…

【AIGC】ChatGPT RAG提取文档内容,高效制作PPT、论文

目录 一、理解 RAG 技术 二、利用 ChatGPT 的 RAG 技术提取文档内容 三、高效制作 PPT 四、高效撰写论文 五、最佳实践与建议 六、工具推荐 随着人工智能生成内容&#xff08;AIGC&#xff09;的快速发展&#xff0c;利用先进的技术工具如 ChatGPT 的 RAG&#xff08;Ret…

R包安装教程,如何安装rjags和infercnv

一.介绍 在数据分析过程中&#xff0c;R语言因其强大的统计分析能力和丰富的包生态系统&#xff0c;成为众多研究人员和数据科学家的首选工具。本文将详细介绍如何在R环境中安装两个重要的R包——rjags和infercnv。rjags用于与JAGS&#xff08;Just Another Gibbs Sampler&…