【ESP32】ESP-IDF开发 | WiFi开发 | UDP用户数据报协议 + UDP客户端和服务器例程
1. 简介
UDP协议(User Datagram Protocol),全称用户数据报协议,它是一种面向非连接的协议,面向非连接指的是在正式通信前不必与对方先建立连接, 不管对方状态就直接发送。至于对方是否可以接收到这些数据内容,UDP协议无法控制,因此说UDP协议是一种不可靠的协议。UDP协议适用于一次只传送少量数据、对可靠性要求不高的应用环境。
因为UDP的数据传输不一定是一对一的,所以也衍生出单播、组播和广播的概念。
1. 单播
单播(unicast),是指封包在计算机网络的传输中,目的地址为单一目标的一种传输方式。它是现今网络应用最为广泛,通常所使用的网络协议或服务大多采用单播传输,例如TCP协议。
2. 多播
组播(multicast),也叫多播或群播。 指把信息同时传递给一组目的地址。它使用策略是最高效的,因为消息在每条网络链路上只需传递一次,而且只有在链路分叉的时候,消息才会被复制。
3. 广播
广播(broadcast),是指封包在计算机网络中传输时,目的地址为网络中所有设备的一种传输方式。
2. lwIP
ESP-IDF使用lwIP库实现TCP/IP协议栈,这个库在大多数嵌入式系统中都有用到,它是一个轻量的TCP/IP协议层套件。
支持以下特性:
- IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over multiple network interfaces
- ICMP (Internet Control Message Protocol) for network maintenance and debugging
- IGMP (Internet Group Management Protocol) for multicast traffic management
- MLD (Multicast listener discovery for IPv6). Aims to be compliant with RFC 2710. No support for MLDv2
- ND (Neighbor discovery and stateless address autoconfiguration for IPv6). Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 (Address autoconfiguration)
- DHCP, AutoIP/APIPA (Zeroconf) and (stateless) DHCPv6
- UDP (User Datagram Protocol) including experimental UDP-lite extensions
- TCP (Transmission Control Protocol) with congestion control, RTT estimation fast recovery/fast retransmit and sending SACKs
- raw/native API for enhanced performance
- Optional Berkeley-like socket API
- TLS: optional layered TCP ("altcp") for nearly transparent TLS for any
- TCP-based protocol (ported to mbedTLS) (see changelog for more info)
- PPPoS and PPPoE (Point-to-point protocol over Serial/Ethernet)
- DNS (Domain name resolver incl. mDNS)
- 6LoWPAN (via IEEE 802.15.4, BLE or ZEP)
支持以下应用层协议:
- HTTP server with SSI and CGI (HTTPS via altcp)
- SNMPv2c agent with MIB compiler (Simple Network Management Protocol), v3 via altcp
- SNTP (Simple network time protocol)
- NetBIOS name service responder
- MDNS (Multicast DNS) responder
- iPerf server implementation
- MQTT client (TLS support via altcp)
3. 例程
例程分别在ESP32上实现TCP客户端和服务端,使用电脑作为另一方进行简单通信测试。需要注意的是,测试时,ESP32和电脑必须处于同一局域网。
电脑端测试使用的上位机为VOFA+,下载地址:VOFA+
3.1 发送端
这个例程配置ESP32为发送端,当连接WiFi热点成功后会向目标IP每隔1秒发送一段数据。
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_mac.h"
#include "nvs_flash.h"
#include "sys/socket.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "netdb.h"
#include "arpa/inet.h"#include <string.h>#define TAG "app"
#define HOST_IP_ADDR "172.16.10.26"
#define HOST_PORT 20001static const char *payload = "Hello from ESP32\r\n";
static TaskHandle_t client_task_handle;static void udp_client_task(void *args)
{struct sockaddr_in dest_addr;dest_addr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR);dest_addr.sin_family = AF_INET;dest_addr.sin_port = htons(HOST_PORT);int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);if (sock < 0) {ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);}ESP_LOGI(TAG, "Socket created, sending to %s:%d", HOST_IP_ADDR, HOST_PORT);while (1) {int err = sendto(sock, payload, strlen(payload), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));if (err < 0) {ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);break;}ESP_LOGI(TAG, "Message sent");vTaskDelay(1000 / portTICK_PERIOD_MS);}close(sock);vTaskDelete(NULL);
}static void wifi_event_handler(void* arg,esp_event_base_t event_base,int32_t event_id,void* event_data)
{if (event_base == IP_EVENT) {if (event_id == IP_EVENT_STA_GOT_IP) {xTaskCreate(udp_client_task, "udp_client", 4096, NULL, 5, &client_task_handle);}} else if (event_base == WIFI_EVENT) {if (event_id == WIFI_EVENT_STA_DISCONNECTED) {vTaskDelete(client_task_handle);} else if (event_id == WIFI_EVENT_STA_START) {esp_wifi_connect();}}
}int app_main()
{/* 初始化NVS */esp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ESP_ERROR_CHECK(nvs_flash_init());}/* 初始化WiFi协议栈 */ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&wifi_event_handler,NULL,NULL));ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,ESP_EVENT_ANY_ID,&wifi_event_handler,NULL,NULL));wifi_config_t wifi_config = {.sta = {.ssid = "QXL",.password = "88888888",.threshold.authmode = WIFI_AUTH_WPA_WPA2_PSK,},};ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));ESP_ERROR_CHECK(esp_wifi_start());return 0;
}
ESP32的WiFi驱动初始化在前面的文章已经有详细的介绍了,这里不再赘述。
因为UDP是面向无连接的,所以编程会相对简单,流程如下:
1. 创建套接字
调用socket函数。第一个参数表示IP协议,这里使用IPv4,对应IP_INET;第二个参数表示socket类型,UDP协议只能填SOCK_DGRAM;第三个参数表示协议栈类型,这里填IPPROTO_IP。函数会返回套接字描述符。
2. 套接字配置(可选)
socket的接收和发送默认是阻塞的,即如果数据不到达就一直等待,所以根据应用的需要设置接收的超时时间。
调用setsockopt函数。第一个参数为套接字描述符;第二个参数为协议层,必须填SOL_SOCKET;第三个参数为设置项,填SO_RCVTIMEO,设置超时时间,当然函数还支持以下配置项:
#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */
#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_DONTLINGER ((int)(~SO_LINGER))
#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */
#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */
#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */
#define SO_RCVBUF 0x1002 /* receive buffer size */
#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */
#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */
#define SO_SNDTIMEO 0x1005 /* send timeout */
#define SO_RCVTIMEO 0x1006 /* receive timeout */
#define SO_ERROR 0x1007 /* get error status and clear */
#define SO_TYPE 0x1008 /* get socket type */
#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */
#define SO_NO_CHECK 0x100a /* don't create UDP checksum */
#define SO_BINDTODEVICE 0x100b /* bind to device */
比较常用的就是SO_RCVTIMEO,设置接收超时;SO_SNDTIMEO,设置发送超时。上面带Unimlemented注释的是ESP-IDF不支持的配置。
每种配置项需要传入的数据是不一样的,用之前建议参考官方的说明文档。设置超时传入的是struct timeval这个结构体。
struct timeval {time_t tv_sec;suseconds_t tv_usec;
};
tv_sec设置秒数,tv_usec设置微秒数。
3. 发送数据
调用sendto函数。参数1为套接字描述符;参数2为数据指针;参数3为数据长度;参数4为标志位,有以下选项:
#define MSG_PEEK 0x01
#define MSG_WAITALL 0x02
#define MSG_OOB 0x04
#define MSG_DONTWAIT 0x08
#define MSG_MORE 0x10
#define MSG_NOSIGNAL 0x20
这些标志位是发送和接收都支持的,比较常用的是MSG_DONTWAIT,像发送和接收函数是阻塞的,使能这个标志位可以让函数立即返回,不等待数据。
参数5为目标地址信息,结构体如下:
struct sockaddr_in {u8_t sin_len;sa_family_t sin_family;in_port_t sin_port;struct in_addr sin_addr;
#define SIN_ZERO_LEN 8char sin_zero[SIN_ZERO_LEN];
};
#endif /* LWIP_IPV4 */
- sin_len:数据长度(一般不需要填);
- sin_family:套接字类型,IPv4填AF_INET,IPv6填AF_INET6,其他填AF_UNSPEC;
- sin_port:端口;
- sin_zero:预留字节(不用管)。
参数6为目标地址结构体长度。
4. 关闭连接
调用close函数。传入套接字描述符即可。
使用上位机时,数据引擎选择“RawData”,数据接口选择UDP,远程IP填写ESP32获取到的IP,本地端口要与ESP32发送报文的端口一致。设置好后,点击左上角的圆形按钮即可启动连接,在下面文本框能看到接收到的消息。
2.2 接收端
这个例程创建一个UDP接收端,接收所有发送至指定端口的UDP包。
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_mac.h"
#include "nvs_flash.h"
#include "sys/socket.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "netdb.h"
#include "arpa/inet.h"#include <string.h>#define TAG "app"
#define SERVER_PORT 20001static TaskHandle_t server_task_handle;static void udp_server_task(void *args)
{char rx_buffer[128];struct sockaddr_in dest_addr;dest_addr.sin_addr.s_addr = htonl(IPADDR_ANY);dest_addr.sin_family = AF_INET;dest_addr.sin_port = htons(SERVER_PORT);int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);if (sock < 0) {ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);}int opt = 0;setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(int));int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));if (err < 0) {ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);goto __exit;}ESP_LOGI(TAG, "Socket bound to port %d", SERVER_PORT);while (1) {struct sockaddr_in source_addr = {0};socklen_t socklen = sizeof(source_addr);memset(rx_buffer, 0, sizeof(rx_buffer));int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&source_addr, &socklen);if (len < 0) {ESP_LOGE(TAG, "recvfrom failed: errno %d", errno);} else {ESP_LOGI(TAG, "Received %d bytes from " IPSTR ":%d, data: %s", len, IP2STR((esp_ip4_addr_t *) &source_addr.sin_addr), source_addr.sin_port, rx_buffer);}}__exit:close(sock);vTaskDelete(NULL);
}static void wifi_event_handler(void* arg,esp_event_base_t event_base,int32_t event_id,void* event_data)
{if (event_base == IP_EVENT) {if (event_id == IP_EVENT_STA_GOT_IP) {xTaskCreate(udp_server_task, "udp_server", 4096, NULL, 5, &server_task_handle);}} else if (event_base == WIFI_EVENT) {if (event_id == WIFI_EVENT_STA_DISCONNECTED) {vTaskDelete(server_task_handle);} else if (event_id == WIFI_EVENT_STA_START) {esp_wifi_connect();}}
}int app_main()
{/* 初始化NVS */esp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ESP_ERROR_CHECK(nvs_flash_init());}/* 初始化WiFi协议栈 */ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&wifi_event_handler,NULL,NULL));ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,ESP_EVENT_ANY_ID,&wifi_event_handler,NULL,NULL));wifi_config_t wifi_config = {.sta = {.ssid = "Your SSID",.password = "Your password",.threshold.authmode = WIFI_AUTH_WPA_WPA2_PSK,},};ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));ESP_ERROR_CHECK(esp_wifi_start());return 0;
}
接收者的流程和发送者差不多,下面只介绍有差异的部分。
1. 创建套接字
参考前面。
2. 配置套接字(可选)
调用setsockopt函数。除了前面介绍到的配置,UDP还支持一个SO_BROADCAST的配置,用来使能广播包的接收,我这里是配置为禁用。
3. 绑定IP(可选)
调用bind函数。参数1为套接字描述符,参数2为IP地址结构体,参数3为结构体长度。通过bind可以绑定监听的IP地址和端口,只有接收到的数据包目标IP和端口一致才会处理,我这里配置接收任意IP,端口为20001。
4. 接收数据
调用recvfrom函数。传入参数和sendto一致,不同的是后面的IP地址结构体是输出参数,不需要初始化,它会返回数据包的源IP信息。
5. 关闭套接字
参考前面。
上位机的配置和前面基本一样,唯一的不同是远程端口要保证和ESP32绑定的端口一致。
相关文章:
【ESP32】ESP-IDF开发 | WiFi开发 | UDP用户数据报协议 + UDP客户端和服务器例程
1. 简介 UDP协议(User Datagram Protocol),全称用户数据报协议,它是一种面向非连接的协议,面向非连接指的是在正式通信前不必与对方先建立连接, 不管对方状态就直接发送。至于对方是否可以接收到这些数据内…...
OpenAI的真正对手?DeepSeek-R1如何用强化学习重构LLM能力边界——DeepSeek-R1论文精读
2025年1月20日,DeepSeek-R1 发布,并同步开源模型权重。截至目前,DeepSeek 发布的 iOS 应用甚至超越了 ChatGPT 的官方应用,直接登顶 AppStore。 DeepSeek-R1 一经发布,各种资讯已经铺天盖地,那就让我们一起…...
es数据同步
Logstash 是 Elastic 技术栈中的一个技术,它是一个数据采集引擎,可以从数据库采集数据到 ES 中。可以通过设置 自增 ID 主键 或 更新时间 来控制数据的自动同步: 自增 ID 主键:Logstatsh 会有定时任务,如果发现有主键…...
【JavaScript笔记】01- 原型及原型链(面试高频内容)
前言 JavaScript作为前端入门三件套之一,也是前端求职的必会知识,重要性不言而喻。 这个系列分享个人学习JavaScript的记录,和大家一起学习讨论。 下面介绍关于原型&原型链的相关重要知识点。 1、构造函数创建对象 function Student(…...
【Python】第五弹---深入理解函数:从基础到进阶的全面解析
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】【Python】 目录 1、函数 1.1、函数是什么 1.2、语法格式 1.3、函数参数 1.4、函数返回值 1.5、变量作用域 1.6、函数…...
动态规划DP 数字三角形模型(模型分析+例题分析+C++代码实现)(数字三角形、摘花生、最低通行费用、方格取数、传纸条)
总体概览 数字三角形 原题链接 AcWing 898.数字三角形 题目描述 给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路…...
2025 最新flutter面试总结
目录 1.Dart是值传递还是引用传递? 2.Flutter 是单引擎还是双引擎 3. StatelessWidget 和 StatefulWidget 在 Flutter 中有什么区别? 4.简述Dart语音特性 5. Navigator 是什么?在 Flutter 中 Routes 是什么? 6、Dart 是不是…...
Java后端之AOP
AOP:面向切面编程,本质是面向特定方法编程 引入依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>示例:记录…...
JS中对数组的操作哪些会改变原数组哪些不会?今天你一定要记下!
JavaScript 数组方法:变更原数组与不变更原数组的区别 在 JavaScript 中,数组是非常常见且重要的数据结构。作为开发者,我们常常需要使用数组方法来处理数组数据。但是,数组的不同方法会以不同的方式影响原数组,它们可…...
ubuntu x64下交叉编译ffmpeg到目标架构为aarch架构的系统
参考链接 https://blog.csdn.net/qq_46396470/article/details/137794498...
Java进阶(二):Java设计模式
目录 设计模式 一.建模语言 二.类之间的关系 1.依赖关系 2.关联关系 3.聚合关系 4.组合关系 5.继承关系 6.实现关系 三.面向对象设计原则 单一职责原则 开闭原则 里氏替换原则 依赖倒置 接口隔离原则 迪米特原则 组合/聚合(关联关系)复用原则 四.23种设计模式…...
python学opencv|读取图像(四十二)使用cv2.add()函数实现多图像叠加
【1】引言 前序学习过程中,掌握了灰度图像和彩色图像的掩模操作: python学opencv|读取图像(九)用numpy创建黑白相间灰度图_numpy生成全黑图片-CSDN博客 python学opencv|读取图像(四十)掩模:三…...
DIY QMK量子键盘
最近放假了,趁这个空余在做一个分支项目,一款机械键盘,量子键盘取自固件名称QMK(Quantum Mechanical Keyboard)。 键盘作为计算机或其他电子设备的重要输入设备之一,通过将按键的物理动作转换为数字信号&am…...
【公式】卢布贬值风险:义乌到俄罗斯贸易的汇率陷阱
卢布贬值风险:义乌到俄罗斯贸易的汇率陷阱 具体实例与推演 假设一位中国义乌的商人,计划出口一批价值100万人民币的商品到俄罗斯。最初的汇率是1人民币兑换100卢布。 初始状态: 商品价值:100万人民币初始汇率:1人民币…...
1月27(信息差)
🌍喜大普奔,适用于 VS Code 的 GitHub Copilot 全新免费版本正式推出,GitHub 全球开发者突破1.5亿 🎄Kimi深夜炸场:满血版多模态o1级推理模型!OpenAI外全球首次!Jim Fan:同天两款国…...
Linux常见问题解决方法--1
常见安全工具、设备 工具 端口及漏洞扫描:Namp、Masscan 抓包:Wireshark,Burpsuite、Fiddler、HttpCanary Web自动化安全扫描:Nessus、Awvs、Appscan、Xray 信息收集:Oneforall、hole 漏洞利用:MSF、…...
Python 数据清洗与处理常用方法全解析
在数据处理与分析过程中,缺失值、重复值、异常值等问题是常见的挑战。本文总结了多种数据清洗与处理方法:缺失值处理包括删除缺失值、固定值填充、前后向填充以及删除缺失率高的列;重复值处理通过删除或标记重复项解决数据冗余问题࿱…...
《企业应用架构模式》笔记
领域逻辑 表模块和数据集一起工作-> 先查询出一个记录集,再根据数据集生成一个(如合同)对象,然后调用合同对象的方法。 这看起来很想service查询出一个对象,但调用的是对象的方法,这看起来像是充血模型…...
顶刊JFR|ROLO-SLAM:首个针对不平坦路面的车载Lidar SLAM系统
摘要 基于激光雷达(LiDAR)的同步定位与地图构建(SLAM)被认为是在恶劣环境中提供定位指导的一种有效方法。然而,现成的基于激光雷达的SLAM方法在经过不平坦地形时,尤其是在垂直方向相关的部分,会…...
第05章 09 使用Lookup绘制地形数据高程着色图
在VTK(Visualization Toolkit)中,可以使用颜色查找表(Lookup Table,简称LUT)来根据高程数据对地形进行着色。以下是一个示例代码,展示了如何使用VTK和C来读取地形数据,并使用颜色查找…...
【深度学习入门_机器学习理论】K近邻法(KNN)
本部分主要为机器学习理论入门_K近邻法(KNN),书籍参考 “ 统计学习方法(第二版)”。 学习目标: 了解k近邻算法的基本概念、原理、应用;熟悉k近邻算法重要影响要素;熟悉kd树原理与优化应用。 开始本算法之…...
基于Django的Boss直聘IT岗位可视化分析系统的设计与实现
【Django】基于Django的Boss直聘IT岗位可视化分析系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用Python作为主要开发语言,利用Django这一高效、安全的W…...
编程语言中的常见Bug及解决方案
在编程过程中,不同语言有其独特的特性和挑战,这也导致了各种常见Bug的出现。本文将总结几种主流编程语言中的常见Bug,包括JavaScript、Python、C/C、Java和Go,并提供相应的解决方案和案例。 一、JavaScript中小数相加精度不准确的…...
DeepSeek API 的获取与对话示例
代码文件下载:Code 在线链接:Kaggle | Colab 文章目录 注册并获取API环境依赖设置 API单轮对话多轮对话流式输出更换模型 注册并获取API 访问 https://platform.deepseek.com/sign_in 进行注册并登录: 新用户注册后将赠送 10 块钱余额&#…...
数据库SQLite和SCADA DIAView应用教程
课程简介 此系列课程大纲主要包含七个课时。主要使用到的开发工具有:SQLite studio 和 SCADA DIAView。详细的可成内容大概如下: 1、SQLite 可视化管理工具SQLite Studio :打开数据库和查询数据;查看视频 2、创建6个变量&#x…...
Elasticsearch+kibana安装(简单易上手)
下载ES( Download Elasticsearch | Elastic ) 将ES安装包解压缩 解压后目录如下: 修改ES服务端口(可以不修改) 启动ES 记住这些内容 验证ES是否启动成功 下载kibana( Download Kibana Free | Get Started Now | Elastic ) 解压后的kibana目…...
(CICD)自动化构建打包、部署(Jenkins + maven+ gitlab+tomcat)
一、平滑发布与灰度发布 **什么叫平滑:**在发布的过程中不影响用户的使用,系统不会因发布而暂停对外服务,不会造成用户短暂性无法访问; **什么叫灰度:**发布后让部分用户使用新版本,其它用户使用旧版本&am…...
Android源码阅读笔记(二)—— 启动模式
Android源码阅读笔记(二)—— 启动模式初章 1、为什么学习启动模式 Activity的启动模式其实是一个在面试中经常会被关注的问题,那么它的重要性体现在哪里? A:在多数的开发场景中,我们似乎也没有怎么关注过…...
AndroidCompose Navigation导航精通2-过渡动画与路由切换
目录 前言路由切换NavControllerBackStackEntry过渡动画过渡原理缩放动画渐隐动画滑动动画动画过渡实战前言 在当今的移动应用开发中,导航是用户与应用交互的核心环节。随着 Android Compose 的兴起,它为开发者提供了一种全新的、声明式的方式来构建用户界面,同时也带来了更…...
PCL ——LevenbergMarquardt非线性最小二乘法拟合圆柱(C++详细过程版)
目录 一、算法概述1、圆柱方程2、LM算法流程二、代码实现三、结果展示一、算法概述 目前求解非线性最小二乘问题常用算法有高斯-牛顿方法(Gauss-Newton algorithm,GN 算法)、列文伯格-马夸尔特方法(Levenberg-Marquardt algorithm,LM 算法)。本文采用 LM 算法进行圆柱拟合。 …...
GD32的GD库开发
所有的Cortex-M处理器都有相同的SysTick定时器,因为CMSIS-Core头文件中定义了一个名为SysTick的结构体。 这个定时器可以用作延时函数,不管是STM32的芯片还是GD32,AT32的芯片,delay函数都可以这么写,只要它是cortex-M…...
DeepSeek R1:推理模型新纪元与价格战
标题:DeepSeek R1:推理模型新纪元与价格战 文章信息摘要: DeepSeek R1的发布标志着推理模型研究的重要转折点,其采用四阶段强化学习训练方法,结合监督微调和拒绝采样,显著提升了模型的推理能力。这一进展不…...
一文简单回顾Java中的String、StringBuilder、StringBuffer
简单说下String、StringBuilder、StringBuffer的区别 String、StringBuffer、StringBuilder在Java中都是用于处理字符串的,它们之间的区别是String是不可变的,平常开发用的最多,当遇到大量字符串连接的时候,就用StringBuilder&am…...
机器学习:支持向量机
支持向量机(Support Vector Machine)是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的广义线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。 假设两类数据可以被 H x : w T x…...
简单的停车场管理系统的C语言实现示例
以下是一个简单的停车场管理系统的C语言实现示例。该示例使用结构体来管理停车场的车位信息,并提供基本车辆进入、离开以及显示停车场状态功能。 #include <stdio.h> #include <stdlib.h> #include <string.h>#define MAX_SLOTS 10 // 最大车位数…...
网络工程师 (3)指令系统基础
一、寻址方式 (一)指令寻址 顺序寻址:通过程序计数器(PC)加1,自动形成下一条指令的地址。这是计算机中最基本、最常用的寻址方式。 跳跃寻址:通过转移类指令直接或间接给出下一条指令的地址。跳…...
基于Python的智慧物业管理系统
【Python】基于Python的智慧物业管理系统(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目背景二、研究目的三、项目意义四、项目功能五、项目创新点六、开发技术介绍七、项目界面展示(部分展示,详细看视频)八、项…...
使用 Vue 3 的 watchEffect 和 watch 进行响应式监视
Vue 3 的 Composition API 引入了 <script setup> 语法,这是一种更简洁、更直观的方式来编写组件逻辑。结合 watchEffect 和 watch,我们可以轻松地监视响应式数据的变化。本文将介绍如何使用 <script setup> 语法结合 watchEffect 和 watch&…...
环境变量
目录 一.概念介绍 1.1命令行参数 二.一个例子,一个环境变量 2.1查看环境变量 2.2如何理解环境变量呢?存储的角度 2.3环境变量最开始从哪里来的呢? 概括: 1. 环境变量的存储 2. 命令查找过程 3. 环境变量表和命令行参数…...
Scale AI 创始人兼 CEO采访
Scale AI 创始人兼 CEO 亚历山大王(Alexander Wang)首次亮相节目接受采访。他的公司专注于为人工智能工具提供准确标注的数据。早在 2022 年,王成为世界上最年轻的白手起家亿万富翁。 美国在全球人工智能竞赛中的地位,以及它与中…...
MongoDB中常用的几种高可用技术方案及优缺点
MongoDB 的高可用性方案主要依赖于其内置的 副本集 (Replica Set) 和 Sharding 机制。下面是一些常见的高可用性技术方案: 1. 副本集 (Replica Set) 副本集是 MongoDB 提供的主要高可用性解决方案,确保数据在多个节点之间的冗余存储和自动故障恢复。副…...
【Erdas实验教程】001:Erdas2022下载及安装教程
文章目录 一、Erdas2022安装教程1. 安装主程序2. 拷贝补丁3. 安装LicenseServer4. 运行软件 二、Erdas2022下载地址 一、Erdas2022安装教程 Erdas2022全新界面如下: 1. 安装主程序 下载安装包并解压,以管理员身份运行 “setup.exe” 或 “setup.vbs”&…...
Python3 【函数】水平考试:精选试题和答案
Python3 【函数】水平考试:精选试题和答案 Python 函数考试试卷及答案。共计30题,其中选择题15题、填空题10题、编程题5题,试卷满分为100分。 一、选择题(每题 2 分,共 30 分) 以下哪个关键字用于定义函数…...
stm8s单片机(三)时钟系统与时钟切换
一个单片机系统要正常运行应包括四个部分: 电源,晶振,复位电路,下载电路。 晶振就是时钟。 stm8有四种时钟源 HSE (High Speed External clock signal)HSE user-ext (High Speed External clock signal user external)HSI (High Speed Inter…...
ChatGPT高效处理图片技巧使用详解
ChatGPT,作为OpenAI开发的预训练语言模型,主要用于生成自然语言文本的任务。然而,通过一些技巧和策略,我们可以将ChatGPT与图像处理模型结合,实现一定程度上的图像优化和处理。本文将详细介绍如何使用ChatGPT高效处理图…...
图漾Halcon版本SDK使用教程【V1.1.0新版本】
文章目录 1.下载并安装 Halcon1.1 下载Halcon软件1.2 安装Halcon 2.下载Camport_Halcon_gentl SDK2.1 下载Camport_Halcon_gentl SDK2.2 Camport Halcon SDK介绍2.3 Halcon SDK环境配置与运行2.3.1 SDK环境配置2.3.2 获取相机支持的参数2.3.3 配置相机参数并运行相机 2.4 遍历H…...
C语言二级
//请编写函数fun(),该函数的功能是:计算并输出给定整数n的所有因 //子(不包括1和自身)之和。规定n的值不大于1000。例如,在主函数 //中从键盘给n输入的值为856,则输出为:sum 763。 //注意&…...
软工_软件工程
2025.01.24:软件工程导论学习笔记 第2节 软件工程 2.1 软件发展 - 四个阶段2.1.1 程序设计2.1.2 程序系统2.1.3 软件工程2.1.4 第四阶段 2.2 软件危机2.2.1 软件危机 - 定义2.2.2 软件危机 - 主要表现 2.1 软件发展 - 四个阶段 2.1.1 程序设计 软件生产个体化&…...
【creo】CREO配置快捷键方式和默认单位
了解CREO工作目录设置 设置快捷方式启动目录,就能自动加载其中的配置。 一、通过键盘快捷方式 保存配置 creo_parametric_customization.ui 文件: 二、通过映射键录制 通过这种方式可以监听鼠标的点击事件。使用键盘快捷方式无法找到需要的动作时候可…...
go理论知识——Go Channel 笔记 [特殊字符]
go理论知识——Go Channel 笔记 📝 1. 基本概念 🧠 1.1 Channel 是什么? Channel 是 Go 语言中用于在不同 Goroutine 之间进行通信的机制。Channel 是类型安全的,意味着你只能发送和接收特定类型的数据。 1.2 Channel 的创建 …...