当前位置: 首页 > article >正文

【ESP32S3】esp32获取串口数据并通过http上传到前端

通过前面的学习(前面没发过,因为其实就是跑它的demo)了解到串口配置以及开启线程实现功能的工作流程,与此同时还有esp32作为STA节点,将数据通过http发送到服务器。
将这两者联合
其实是可以得到一个:esp32获取串口数据并通过http上传到前端,这样的功能的。假设收到的数据是温湿度数据。
文章食用提醒:
本文用到的ESP框架是ESP-IDF,服务器端处理代码格式是js,数据库采用mongoDB。

http part

#define MAX_HTTP_RECV_BUFFER 512
#define MAX_HTTP_OUTPUT_BUFFER 2048static const char *TAG = "HTTP_CLIENT 0313";
static char response_data[1024]; // 自定义缓存空间储存一次响应数据
static int recived_len = 0;      // 自定义变量储存一次响应中接收到分片数据的累计偏移
// http客户端的事件处理回调函数
static esp_err_t http_client_event_handler(esp_http_client_event_t *evt)
{switch (evt->event_id){case HTTP_EVENT_ON_CONNECTED:ESP_LOGI(TAG, "connected to web-server");recived_len = 0;break;case HTTP_EVENT_ON_DATA:if (evt->user_data){memcpy(evt->user_data + recived_len, evt->data, evt->data_len); // 将分片的每一片数据都复制到user_datarecived_len += evt->data_len;//累计偏移更新}break;case HTTP_EVENT_ON_FINISH:ESP_LOGI(TAG, "finished a request and response!");recived_len = 0;break;case HTTP_EVENT_DISCONNECTED:ESP_LOGI(TAG, "disconnected to web-server");recived_len = 0;break;case HTTP_EVENT_ERROR:ESP_LOGE(TAG, "error");recived_len = 0;break;default:break;}return ESP_OK;
}
char* create_json_from_data(float temperature, float humidity) {// 创建根对象cJSON *root = cJSON_CreateObject();// 向JSON对象中添加键值对cJSON_AddNumberToObject(root, "temperature", temperature);cJSON_AddNumberToObject(root, "humidity", humidity);// 将cJSON对象转换为字符串char *json_data = cJSON_Print(root);// 释放cJSON对象占用的内存cJSON_Delete(root);return json_data;
}

uart part

#define CONFIG_UART_TXD 4
#define CONFIG_UART_RXD 5
#define UART_PIN_RTS (-1)
#define UART_PIN_CTS (-1)
#define CONFIG_UART_PORT_NUM      2
#define CONFIG_UART_BAUD_RATE     115200
#define CONFIG_TASK_STACK_SIZE    3072
#define BUF_SIZE (1024)
#define QUEUE_LENGTH 10
static QueueHandle_t xQueue = NULL;
// 假设收到的数据是温湿度数据
typedef struct data_dht11
{float temperature;float humidity;
}data_t;static void uart_rx_task(void *arg) 
{// 配置串口uart_config_t uart_config = {.baud_rate = CONFIG_UART_BAUD_RATE,.data_bits = UART_DATA_8_BITS,.parity    = UART_PARITY_DISABLE,.stop_bits = UART_STOP_BITS_1,.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,.source_clk = UART_SCLK_DEFAULT,};int intr_alloc_flags = 0;#if CONFIG_UART_ISR_IN_IRAMintr_alloc_flags = ESP_INTR_FLAG_IRAM;#endifESP_ERROR_CHECK(uart_driver_install(CONFIG_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, 0));ESP_ERROR_CHECK(uart_param_config(CONFIG_UART_PORT_NUM, &uart_config));ESP_ERROR_CHECK(uart_set_pin(CONFIG_UART_PORT_NUM, CONFIG_UART_TXD, CONFIG_UART_RXD, UART_PIN_RTS, UART_PIN_CTS));uint8_t *data = (uint8_t *)malloc(BUF_SIZE);// 接收数据,把数据存放在队列里while (1) {int len = uart_read_bytes(CONFIG_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);if(len > 0) {data[len] = '\0';data_t item;sscanf((char*)data, "%f %f", &item.temperature, &item.humidity); // 假设数据格式为"temperature humidity"xQueueSend(xQueue, &item, portMAX_DELAY);}vTaskDelay(pdMS_TO_TICKS(10)); // 让出CPU时间片,分给其他任务}free(data);
}

main part

void app_main(void)
{esp_err_t ret;nvs_flash_init();esp_netif_init();esp_event_loop_create_default();example_connect();xQueue = xQueueCreate(QUEUE_LENGTH, sizeof(data_t));if (xQueue == NULL) {ESP_LOGE(TAG, "Failed to create queue");return;}xTaskCreate(uart_rx_task, "uart_rx_task", 2048, NULL, configMAX_PRIORITIES-1, NULL);// http配置const esp_http_client_config_t cfg = {.url = "http://124.223.186.76:3000",.event_handler = http_client_event_handler,.user_data = response_data,.disable_auto_redirect = true, // 根据需求选择是否禁用自动重定向.transport_type = HTTP_TRANSPORT_OVER_TCP, // 强制使用TCP传输.timeout_ms = 10000, // 设置超时时间为10秒};//使用http服务器配置参数对http客户端初始化esp_http_client_handle_t httpclient = esp_http_client_init(&cfg);// 进入循环接收串口数据并发给服务器上while (true) {data_t item;if(xQueueReceive(xQueue, &item, portMAX_DELAY) == pdPASS){// 调用函数创建JSON格式的数据char *json_data = create_json_from_data(item.temperature, item.humidity);// 设置HTTP请求的各种参数esp_http_client_set_method(httpclient, HTTP_METHOD_POST);esp_http_client_set_url(httpclient, "/add");// 添加或更新"Connection"头为"close"esp_http_client_set_header(httpclient, "Connection", "close");// 设置请求头esp_http_client_set_header(httpclient, "Content-Type", "application/json");// 设置请求体为刚刚创建的JSON数据esp_http_client_set_post_field(httpclient, json_data, strlen(json_data));// 初始化重试计数器int max_retries = 3; // 最大重试次数esp_err_t ret;for(int retry = 0; retry <= max_retries; ++retry) {ret = esp_http_client_perform(httpclient);if(ret == ESP_OK) {// 请求成功,打印响应数据printf("POST:%s\n", response_data);ESP_LOGD(TAG,"HTTP POST Status = %d, content_length = %lld",esp_http_client_get_status_code(httpclient),esp_http_client_get_content_length(httpclient));break; // 成功后退出循环} else {if(retry < max_retries) {// 如果还有剩余重试次数,则等待一段时间后重试ESP_LOGW(TAG, "Attempt %d failed, retrying in 1 second...", retry + 1);vTaskDelay(pdMS_TO_TICKS(1000)); // 等待1秒后再重试} else {// 达到最大重试次数,记录错误信息ESP_LOGE(TAG, "Error occurred during HTTP request after %d retries, failed: %s", max_retries, esp_err_to_name(ret));}}}free(json_data); // 释放动态分配的内存}else {// 处理超时或其他错误情况ESP_LOGW(TAG, "Failed to receive data from queue.");}}esp_http_client_cleanup(httpclient);//清空http客户端描述符vQueueDelete(xQueue); // 删除队列
}

merge code

/*
built date: 2025年3月21日17点48分
builder: kiro-1023
*/
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "esp_system.h"
#include <esp_event.h>
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_log.h"#include <nvs_flash.h>
#include "esp_netif.h"
#include "protocol_examples_common.h"#include "esp_http_client.h"
#include "cJSON.h"#include <string.h>
#include <sys/param.h>
#include <stdlib.h>
#include <ctype.h>
#include "protocol_examples_utils.h"
#include "esp_tls.h"
#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
#include "esp_crt_bundle.h"
#endif#define MAX_HTTP_RECV_BUFFER 512
#define MAX_HTTP_OUTPUT_BUFFER 2048#define CONFIG_UART_TXD 4
#define CONFIG_UART_RXD 5
#define UART_PIN_RTS (-1)
#define UART_PIN_CTS (-1)#define CONFIG_UART_PORT_NUM      2
#define CONFIG_UART_BAUD_RATE     115200
#define CONFIG_TASK_STACK_SIZE    3072#define BUF_SIZE (1024)
#define QUEUE_LENGTH 10
static QueueHandle_t xQueue = NULL;static const char *TAG = "HTTP_CLIENT 0313";static char response_data[1024]; // 自定义缓存空间储存一次响应数据
static int recived_len = 0;      // 自定义变量储存一次响应中接收到分片数据的累计偏移typedef struct data_dht11
{float temperature;float humidity;
}data_t;static void uart_rx_task(void *arg) {uart_config_t uart_config = {.baud_rate = CONFIG_UART_BAUD_RATE,.data_bits = UART_DATA_8_BITS,.parity    = UART_PARITY_DISABLE,.stop_bits = UART_STOP_BITS_1,.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,.source_clk = UART_SCLK_DEFAULT,};int intr_alloc_flags = 0;#if CONFIG_UART_ISR_IN_IRAMintr_alloc_flags = ESP_INTR_FLAG_IRAM;#endifESP_ERROR_CHECK(uart_driver_install(CONFIG_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, 0));ESP_ERROR_CHECK(uart_param_config(CONFIG_UART_PORT_NUM, &uart_config));ESP_ERROR_CHECK(uart_set_pin(CONFIG_UART_PORT_NUM, CONFIG_UART_TXD, CONFIG_UART_RXD, UART_PIN_RTS, UART_PIN_CTS));uint8_t *data = (uint8_t *)malloc(BUF_SIZE);while (1) {int len = uart_read_bytes(CONFIG_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);if(len > 0) {data[len] = '\0';data_t item;sscanf((char*)data, "%f %f", &item.temperature, &item.humidity); // 假设数据格式为"temperature humidity"xQueueSend(xQueue, &item, portMAX_DELAY);}vTaskDelay(pdMS_TO_TICKS(10)); // 让出CPU时间片,分给其他任务}free(data);
}// http客户端的事件处理回调函数
static esp_err_t http_client_event_handler(esp_http_client_event_t *evt)
{switch (evt->event_id){case HTTP_EVENT_ON_CONNECTED:ESP_LOGI(TAG, "connected to web-server");recived_len = 0;break;case HTTP_EVENT_ON_DATA:if (evt->user_data){memcpy(evt->user_data + recived_len, evt->data, evt->data_len); // 将分片的每一片数据都复制到user_datarecived_len += evt->data_len;//累计偏移更新}break;case HTTP_EVENT_ON_FINISH:ESP_LOGI(TAG, "finished a request and response!");recived_len = 0;break;case HTTP_EVENT_DISCONNECTED:ESP_LOGI(TAG, "disconnected to web-server");recived_len = 0;break;case HTTP_EVENT_ERROR:ESP_LOGE(TAG, "error");recived_len = 0;break;default:break;}return ESP_OK;
}char* create_json_from_data(float temperature, float humidity) {// 创建根对象cJSON *root = cJSON_CreateObject();// 向JSON对象中添加键值对cJSON_AddNumberToObject(root, "temperature", temperature);cJSON_AddNumberToObject(root, "humidity", humidity);// 将cJSON对象转换为字符串char *json_data = cJSON_Print(root);// 释放cJSON对象占用的内存cJSON_Delete(root);return json_data;
}void app_main(void)
{esp_err_t ret;nvs_flash_init();esp_netif_init();esp_event_loop_create_default();example_connect();xQueue = xQueueCreate(QUEUE_LENGTH, sizeof(data_t));if (xQueue == NULL) {ESP_LOGE(TAG, "Failed to create queue");return;}xTaskCreate(uart_rx_task, "uart_rx_task", 2048, NULL, configMAX_PRIORITIES-1, NULL);const esp_http_client_config_t cfg = {.url = "http://124.223.186.76:3000",.event_handler = http_client_event_handler,.user_data = response_data,.disable_auto_redirect = true, // 根据需求选择是否禁用自动重定向.transport_type = HTTP_TRANSPORT_OVER_TCP, // 强制使用TCP传输.timeout_ms = 10000, // 设置超时时间为10秒};//使用http服务器配置参数对http客户端初始化esp_http_client_handle_t httpclient = esp_http_client_init(&cfg);while (true) {data_t item;if(xQueueReceive(xQueue, &item, portMAX_DELAY) == pdPASS){// 调用函数创建JSON格式的数据char *json_data = create_json_from_data(item.temperature, item.humidity);// 设置HTTP请求的各种参数esp_http_client_set_method(httpclient, HTTP_METHOD_POST);esp_http_client_set_url(httpclient, "/add");// 添加或更新"Connection"头为"close"esp_http_client_set_header(httpclient, "Connection", "close");// 设置请求头esp_http_client_set_header(httpclient, "Content-Type", "application/json");// 设置请求体为刚刚创建的JSON数据esp_http_client_set_post_field(httpclient, json_data, strlen(json_data));// 初始化重试计数器int max_retries = 3; // 最大重试次数esp_err_t ret;for(int retry = 0; retry <= max_retries; ++retry) {ret = esp_http_client_perform(httpclient);if(ret == ESP_OK) {// 请求成功,打印响应数据printf("POST:%s\n", response_data);ESP_LOGD(TAG,"HTTP POST Status = %d, content_length = %lld",esp_http_client_get_status_code(httpclient),esp_http_client_get_content_length(httpclient));break; // 成功后退出循环} else {if(retry < max_retries) {// 如果还有剩余重试次数,则等待一段时间后重试ESP_LOGW(TAG, "Attempt %d failed, retrying in 1 second...", retry + 1);vTaskDelay(pdMS_TO_TICKS(1000)); // 等待1秒后再重试} else {// 达到最大重试次数,记录错误信息ESP_LOGE(TAG, "Error occurred during HTTP request after %d retries, failed: %s", max_retries, esp_err_to_name(ret));}}}free(json_data); // 释放动态分配的内存}else {// 处理超时或其他错误情况ESP_LOGW(TAG, "Failed to receive data from queue.");}}esp_http_client_cleanup(httpclient);//清空http客户端描述符vQueueDelete(xQueue); // 删除队列
}

接着在Linux下写服务器的处理内容

index.js code

const express = require('express')
const bodyParser = require('body-parser')
const { MongoClient } = require('mongodb');
const request = require('request')
const fs = require('fs')const app = express()
app.use(bodyParser.json())// MongoDB URI 和客户端初始化,这里的账号密码记得填你自己的
const uri = "mongodb://yourusername:yourpasswd@localhost:27017/myDatabase?authSource=admin";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });let db; // 定义一个变量用于存储数据库引用async function startServer() {try {await client.connect(); // 连接到MongoDBconsole.log("Connected to database");db = client.db('myDatabase'); // 获取数据库引用,这里的myDatabase是数据库名// 监听端口app.listen(3000, '0.0.0.0', () => {console.log('mwt server running at http://124.223.186.76:3000');});} catch (err) {console.error("Failed to connect to the database:", err);process.exit(1); // 如果无法连接数据库,则退出程序}
}startServer();// 处理外设数据上传的POST请求
app.post('/add', async (req, res) => {const data = req.body; // 直接获取到JSON对象console.log("Received data:", data); // 新增日志记录if (!data.temperature || !data.humidity) {return res.status(400).json({ result: false, message: "Missing parameters" });}try {if (!db) {return res.status(500).json({ result: false, message: "Database connection not established" });}// 插入文档到集合'readings'const collection = db.collection('readings'); // 使用之前定义的db变量,这里的readings是表名await collection.insertOne(data);console.log(`A document was inserted with the _id: ${data._id}`);// 写到当前路径下的log里fs.appendFile('sensor_data.log', JSON.stringify(data) + '\n', (err) => {if (err) throw err;});res.json({result: true,method: "POST",message: "Data received and saved successfully"});} catch (err) {console.error("Failed to save data:", err.stack);res.status(500).json({ result: false, message: "Failed to save data" });}
});
// 获取所有读数并简单地显示在前端,也可以另创一个html文件或新建一个web工程按实际情况导进去
app.get('/readings', async (req, res) => {try {const collection = db.collection('readings');  //表名是readings// 查找所有文档const readings = await collection.find({}).toArray();// 返回HTML页面或JSON数据res.send(`<html><head><title>Sensor Readings</title></head><body><h1>Sensor Readings</h1><ul>${readings.map(r => `<li>Temperature: ${r.temperature}, Humidity: ${r.humidity}</li>`).join('')}</ul></body></html>`);} catch (err) {console.error("Failed to fetch data:", err);res.status(500).send("Error fetching data");}
});

在服务器部署nodejs,并安装配置mongoDB环境,这样前端就可以从mongoDB拿到数据并显示出来了。
假设已经安装好nodejs,也装好了mongoDB。
新建一个目录,我这里叫my_node_app0314,然后把上面的js处理脚本放进这个文件夹里,这里我把它命名为index.js
1
然后启动应用

node index.js

如果看到active running就说明启动好了

ubuntu@VM-12-13-ubuntu:~$ sudo systemctl status my_node_app0314.service # 看状态
● my_node_app0314.service - My Node.js ApplicationLoaded: loaded (/etc/systemd/system/my_node_app0314.service; enabled; vendor preset: enabled)Active: active (running) since Fri 2025-03-21 10:43:59 CST; 24s agoMain PID: 316472 (node)Tasks: 11 (limit: 8816)Memory: 24.6MCGroup: /system.slice/my_node_app0314.service└─316472 /usr/bin/node /home/ubuntu/my_node_app0314/index.jsMar 21 10:43:59 VM-12-13-ubuntu systemd[1]: Started My Node.js Application.
Mar 21 10:44:00 VM-12-13-ubuntu node[316472]: (node:316472) [MONGODB DRIVER] Warning: useNewUrlParser i>
Mar 21 10:44:00 VM-12-13-ubuntu node[316472]: (Use `node --trace-warnings ...` to show where the warnin>
Mar 21 10:44:00 VM-12-13-ubuntu node[316472]: (node:316472) [MONGODB DRIVER] Warning: useUnifiedTopolog>
Mar 21 10:44:00 VM-12-13-ubuntu node[316472]: Connected to database
Mar 21 10:44:00 VM-12-13-ubuntu node[316472]: mwt server running at http://124.223.186.76:3000
lines 1-15/15 (END)

最后

编译运行esp32s3,并打开浏览器
3
很好的是esp32s3支持很多的i2c扩展,我这里用串口只是为了方便,dht11是单总线的,以上数据来自串口助手。
【全文完】

参考链接

:ESP32+idf开发之WIFI通信入门(5)HTTP通信
跑了参考链接的代码
这个博主的文章代码亲测可用,在这里也很谢谢他。

相关文章:

【ESP32S3】esp32获取串口数据并通过http上传到前端

通过前面的学习&#xff08;前面没发过&#xff0c;因为其实就是跑它的demo&#xff09;了解到串口配置以及开启线程实现功能的工作流程&#xff0c;与此同时还有esp32作为STA节点&#xff0c;将数据通过http发送到服务器。 将这两者联合 其实是可以得到一个&#xff1a;esp32获…...

代购系统:架构设计、功能实现与用户界面优化

一、引言 随着全球化的加速&#xff0c;代购业务已成为电商领域的重要组成部分。代购系统不仅需要满足用户对商品的需求&#xff0c;还需提供高效、安全、便捷的购物体验。本文将从技术架构设计、功能实现、用户界面优化三个方面深入探讨代购系统的设计与实现。 二、技术架构…...

《一本书讲透Elasticsearch:原理、进阶与工程实践》读书笔记

1&#xff1a;es的组成部分&#xff1a; Elasticsearch 引擎&#xff1a;核心组件&#xff0c;处理索引和搜索请求 Kibana&#xff1a;es的可视化的数据界面&#xff0c;用于分析和展示数据 Beats&#xff08;可选&#xff09;轻量级的日志采集器 2&#xff1a;基本概念 es开…...

Android15查看函数调用关系

Android15 Camera3中打印函数调用栈 1.使用CallStack跟踪函数调用 修改涉及三个内容&#xff1a; Android.bp中添加对CallStack的引用。CallStack被打包在libutilscallstack.so。代码中包含CallStack的头文件。代码中调用CallStack接口&#xff0c;打印函数调用栈。 例子&am…...

Spring Boot(十七):集成和使用Redis

Redis(Remote Dictionary Server,远程字典服务器)是一个开源的、基于内存的数据结构存储系统,它可以用作数据库、缓存和消息中间件。Spring Boot 中集成和使用Redis主要涉及以下几个步骤: 添加依赖 在项目的pom.xml文件中添加Redis的依赖。Spring Boot提供了对Redis的集…...

macOS 15 通过 MacPorts 安装 PHP 7 构建错误找不到符号在 dns.o 中解决方法

构建遇到的问题如下&#xff1a; "_res_9_dn_expand", referenced from:_php_parserr in dns.o_php_parserr in dns.o_php_parserr in dns.o_php_parserr in dns.o_php_parserr in dns.o_php_parserr in dns.o_zif_dns_get_mx in dns.o..."_res_9_dn_skipname&…...

练习:猜数字小游戏

需求&#xff1a; 程序自动生成一个 1 - 100 之间的随机数字&#xff0c;使用程序实现猜出这个数字是多少&#xff1f; 代码&#xff1a; //猜数字小游戏 package demo01; import java.util.Random; import java.util.Scanner; public class HelloJava {public static void …...

EMQX Dashboard

EMQX Dashboard EMQX理论基础 https://blog.csdn.net/liudachu/article/details/146495030 1 Dashboard简介 EMQX 提供了一个内置的管理控制台&#xff0c;即 EMQX Dashboard。方便用户通过 Web 页面就能轻松管理和监控 EMQX 集群&#xff0c;并配置和使用所需的各项功能。 访…...

PC名词解释-笔记本的S0,S1,S2,S3,S4,S5状态

​&#x1f393;作者简介&#xff1a;程序员转项目管理领域优质创作者 &#x1f48c;个人邮箱&#xff1a;[2707492172qq.com] &#x1f310;PMP资料导航&#xff1a;PM菜鸟&#xff08;查阅PMP大纲考点&#xff09; &#x1f4a1;座右铭&#xff1a;上善若水&#xff0c;水善利…...

uniapp自定义目录tree(支持多选、单选、父子联动、全选、取消、目录树过滤、异步懒加载节点、v-model)vue版本

先看案例&#xff1a; 效果&#xff1a; 数据结构如下&#xff1a; const themeList ref([{id: 1,name: 内蒙古,children: [{id: 3,name: 街道1,children: [{id: 4,name: 小区1}]}]},{id: 2,name: 北京,children: [{id: 6,name: 街道2}]} ]) 参数配置&#xff1a; 属性名类…...

【10】Strongswan collections —— array

//array 代码解释与测试 #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <stdarg.h>#define INIT(this, ...) ({ (this) malloc(sizeof(*(this))); \*(this) (typeof…...

ESP32S3 WIFI 实现TCP服务器和静态IP

一、 TCP服务器代码 代码由station_example_main的官方例程修改 /* WiFi station ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an &q…...

docker中安装 python

ubuntu 1、安装源码编译所需依赖 apt-get install -y gcc g make cmake libsqlite3-dev zlib1g-dev libssl-dev libffi-dev 2、下载python安装包 python-release安装包下载_开源镜像站-阿里云 3、解压安装 tar -zxvf Python-3.7.5.tgz cd Python-3.7.5 ./configure --prefix…...

VSCode Flutter 快捷键

扩展安装&#xff1a; Flutter Widget Snippets Flutter Flutter Files 1.StatelessWidget切换StatefulWidget快捷键 1.1 将光标放在 StatelessWidget 上。 1.2 按下快捷键&#xff1a; Windows/Linux: Ctrl . macOS: Cmd . 1.3 在弹出的菜单中选择 "Convert to Stat…...

Java面试黄金宝典18

1. 如何找到一条单链表的中间结点 定义 单链表是一种常见的数据结构&#xff0c;每个节点包含数据和指向下一个节点的指针。找到单链表的中间结点&#xff0c;即找出链表中位于中间位置的节点。可借助快慢指针法达成&#xff0c;快指针每次移动两步&#xff0c;慢指针每次移动…...

设计秒杀系统(高并发的分布式系统)

学海无涯&#xff0c;志当存远。燃心砺志&#xff0c;奋进不辍。 愿诸君得此鸡汤&#xff0c;如沐春风&#xff0c;事业有成。 若觉此言甚善&#xff0c;烦请赐赞一枚&#xff0c;共励学途&#xff0c;同铸辉煌&#xff01; 思路 处理高并发 流量削峰&#xff1a;限流&#xf…...

【面试题】利用Promise实现Websocket阻塞式await wsRequest() 请求

逻辑实现过程 1. 目标与基础设计 目标&#xff1a;实现一个类似 HTTP 请求的阻塞式调用接口&#xff08;如 await wsRequest(...)&#xff09;&#xff0c;让开发者无需手动处理 WebSocket 的事件回调&#xff0c;而是通过 Promise 和 async/await 获得同步体验。 基础设计&a…...

数据库----单表、多表

数据库 create database 数据库名称;---创建数据库create database 数据库名称 default charsetutf8mb4;---创建数据库&#xff0c;同时指定编码show databases;---查看当前数据库管理下存在多少数据库show databases like "db_%";---查询以db_开头的数据库select d…...

ubuntu 22.04 一键安装 lxd

LXD系列 LXD是一个现代、安全且功能强大的系统容器和虚拟机管理器。 它为在容器或虚拟机中运行和管理完整的 Linux 系统提供了统一的体验。LXD 支持大量 Linux 发行版的映像(官方 Ubuntu 映像和社区提供的映像),并且围绕...

HO与OH差异之Navigation三

在上一篇内容中我们介绍了HO与OH差异之Navigator&#xff0c;我们也了解了Navigator的基本概念和大致了解了一下他的基础用法&#xff0c;既然谈到差异肯定就不止这两种差异&#xff0c;今天就让我们来了解第三种差异NavRouter&#xff0c;其中在HO中我们并没有这种路由方式但是…...

Zookeeper运维指南:服务端与客户端常用命令详解

#作者&#xff1a;任少近 文章目录 1 Zookeeper服务端常用命令2 Zookeeper客户端常用命令2.1Ls命令2.2创建节点create2.3Get命令2.4删除命令2.5修改命令 1 Zookeeper服务端常用命令 启动ZK服务: bin/zkServer.sh start # ./zkServer.sh startZooKeeper JMX enabled by defau…...

linux scp复制多层级文件夹到另一服务器免密及脚本配置

文章目录 生成 SSH 密钥对将公钥复制到目标服务器验证免密登录scp 多级文件夹复制脚本 生成 SSH 密钥对 在本地机器上&#xff0c;使用 ssh-keygen 命令生成 SSH 密钥对。打开终端并执行以下命令&#xff1a; ssh-keygen -t rsa 按提示连续按回车键&#xff0c;默认会在 ~/.ss…...

模型压缩与迁移:基于蒸馏技术的实战教程

1.前言 模型蒸馏&#xff08;Model Distillation&#xff09;&#xff0c;又称为知识蒸馏&#xff08;Knowledge Distillation&#xff09;&#xff0c;是一种将大型、复杂的模型&#xff08;通常称为教师模型&#xff0c;Teacher Model&#xff09;的知识转移到小型、简单模型…...

XSS通关技巧

目录 第一关&#xff1a; 第二关&#xff1a; 第三关&#xff1a; 第四关&#xff1a; 第五关&#xff1a; 第六关&#xff1a; 第七关&#xff1a; 第八关&#xff1a; 第九关&#xff1a; 第十关&#xff1a; 第十一关&#xff1a; 第十二关&#xff1a; 第十三关&#xff1a…...

el-tree树多选,将选中的树对象中某个字段值改为true,并过滤出所有为true的对象,组成新的数组

功能实现&#xff1a; el-tree树多选&#xff0c;将选中的树对象中某个字段值改为true,并过滤出所有为true的对象&#xff0c;组成新的数组提交给后端 <template><div><!-- 树形菜单 --><el-tree:data"stageList"show-checkboxdefault-expand-…...

大文件版本管理git-lfs

1. 安装 Git Large File Storage (LFS) 是一个 开源的 Git 扩展&#xff0c;用于替换 Git 仓库中的大文件&#xff0c;用指针文件替代实际的大文件&#xff0c;可以在保持仓库轻量级的同时&#xff0c;有效地管理大型文件。 如果install提示失败&#xff0c;多试几次&#xf…...

Android RemoteViews:跨进程 UI 更新的奥秘与实践

目录 一、RemoteViews 的舞台:使用场景 (一)通知栏:动态交互的窗口 (二)桌面小部件:桌面上的动态名片 二、RemoteViews 的本质:定义与架构 (一)什么是 RemoteViews? (二)架构设计:层次分明的协作 (三)操作限制:能力边界在哪里? 三、RemoteViews 的引擎…...

es 3期 第27节-运用Script脚本实现复杂需求

#### 1.Elasticsearch是数据库&#xff0c;不是普通的Java应用程序&#xff0c;传统数据库需要的硬件资源同样需要&#xff0c;提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库&#xff0c;不是关系型数据库&#xff0c;不具备严格的ACID事务特性&#xff…...

玩转python: 掌握Python常用库之数据分析pandas

pandas是Python中最强大的数据处理和分析库之一&#xff0c;它提供了高效、灵活且易于使用的数据结构&#xff0c;使数据清洗、转换和分析变得简单直观。 1、pandas库简介 pandas由Wes McKinney于2008年开发&#xff0c;名称来源于"panel data"&#xff08;面板数据…...

融合YOLO11与行为树的人机协作智能框架:动态工效学优化与自适应安全决策

人工智能技术要真正发挥其价值&#xff0c;必须与生产生活深度融合&#xff0c;为产业发展和人类生活带来实际效益。近年来&#xff0c;基于深度学习的机器视觉技术在工业自动化领域取得了显著进展&#xff0c;其中YOLO&#xff08;You Only Look Once&#xff09;算法作为一种…...