ESP32-IDF http请求崩溃问题分析与解决

news2024/9/27 19:22:31

文章目录

  • esp32s3 http请求崩溃
  • 问题代码讨论
  • 修正后不崩溃的代码
  • esp32相关文章

ESP32S3板子, 一运行http请求百度网站的例子, 就会panic死机, 记录下出现及解决过程.

esp32s3 http请求崩溃

一执行http请求的perform就会崩溃,
打印如图
在这里插入图片描述
ESP32-IDF 的http请求代码是根据官方demo来改的,
第一步先连接wifi,
连接上后执行http get请求百度网站.
理论上写法是没问题的,但是运行到板子上发现很容易崩溃.

问题代码讨论

会在可能有问题的地方注释,有4个问题点,具体看代码 ,
最主要问题是运行内存有限, 容易发生栈或堆溢出或越界导致崩溃.

#include <stdio.h>
#include <pthread.h>

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_wifi.h"
#include "esp_tls.h"
#include "esp_crt_bundle.h"
#include "esp_http_client.h"


static const char *TAG = "HTTP_REQUEST";

// 这里的buffer要适当, 如果改太大了, 比如10240就可能导致死机, 要根据实际运行结果做调整
#define MAX_HTTP_OUTPUT_BUFFER 2048
#define HTTP_URL "http://www.baidu.com"

// HTTP 请求的处理函数
esp_err_t http_event_handler(esp_http_client_event_t *evt)
{
    // 缓存http响应的buffer
    static char *output_buffer;
    // 已经读取的字节数
    static int output_len;
    switch(evt->event_id) {
        case HTTP_EVENT_ERROR:
            ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
            break;
        case HTTP_EVENT_ON_HEADER:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
            break;
        case HTTP_EVENT_ON_DATA:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);

            if (!esp_http_client_is_chunked_response(evt->client)) {
                if (evt->user_data) {
                    // 问题1: 这里没有做防溢出限制, 当http返回的数据长度趤过预留的buffer大小MAX_HTTP_OUTPUT_BUFFER时就会溢出崩溃
                    memcpy(evt->user_data + output_len, evt->data, evt->data_len);
                } else {
                    if (output_buffer == NULL) {
                        // 问题2: 这里直接用malloc申请http返回的数据长度的堆空间, 实测在esp32s3板子上跑会崩溃
                        output_buffer = (char *) malloc(esp_http_client_get_content_length(evt->client));
                        output_len = 0;
                        if (output_buffer == NULL) {
                            ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
                            return ESP_FAIL;
                        }
                    }
                    memcpy(output_buffer + output_len, evt->data, evt->data_len);
                }
                output_len += evt->data_len;
            }

            break;
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
            if (output_buffer != NULL) {
                // Response is accumulated in output_buffer. Uncomment the below line to print the accumulated response
                // ESP_LOG_BUFFER_HEX(TAG, output_buffer, output_len);
                free(output_buffer);
                output_buffer = NULL;
            }
            output_len = 0;
            break;
        case HTTP_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
            if (output_buffer != NULL) {
                free(output_buffer);
                output_buffer = NULL;
            }
            output_len = 0;
            break;
    }
    return ESP_OK;
}

void request(const char *url) {
    printf("request  -----------1\n");
    // 响应结果放在这里
    char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};

    // 创建一个 HTTP 客户端配置
    esp_http_client_config_t config = {
            .method = HTTP_METHOD_GET,
            .url = url,
            .event_handler = http_event_handler,
            .user_data = local_response_buffer,
            .disable_auto_redirect = true,
    };

    // 创建一个 HTTP 客户端并执行 GET 请求
    esp_http_client_handle_t client = esp_http_client_init(&config);
    printf("request  -----------2\n");
    esp_err_t err = esp_http_client_perform(client); // 请求百度网页时,一执行这行系统就会崩溃
    printf("request  -----------3\n");

    // 检查请求是否成功
    if (err == ESP_OK) {
        int len =  esp_http_client_get_content_length(client);
        ESP_LOGI(TAG, "Status = %d, content_length = %d",
                 esp_http_client_get_status_code(client),//状态码
                 len);//数据长度

    } else {
        printf("HTTP GET request failed: %s\n", esp_err_to_name(err));
    }
    printf("Response: %.*s\n", strlen(local_response_buffer), local_response_buffer);

    //断开并释放资源
    esp_http_client_cleanup(client);
    printf("request  -----------4\n");
}

void http_test_task(void *arg)
{
    sleep(15);
    request(HTTP_URL);

    vTaskDelete(NULL);
}

/**
 * @brief WiFi 的事件循环Handler
 * @param arg
 * @param event_base
 * @param event_id
 * @param event_data
 */
void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    printf("wifi_event_handler base:%s, id:%d\n", event_base, event_id);
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    {
        printf("esp_wifi_connect\n");
        esp_wifi_connect();
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        printf("esp_wifi_connect\n");
        esp_wifi_connect();
    }

    if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
        ESP_LOGI("ESP32", "IP地址:: " IPSTR, IP2STR(&event->ip_info.ip));

        //request(HTTP_URL); 问题点3: 获取到ip地址后,不要直接在这里执行http请求, 否则会直接崩溃
    }
}

void app_main(void)
{
    esp_err_t ret = nvs_flash_init(); // 初始化默认NVS分区
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase()); // 擦除默认NVS分区
        ret = nvs_flash_init();             // 初始化默认NVS分区
    }
    ESP_ERROR_CHECK(ret);
    ESP_ERROR_CHECK(esp_netif_init());                // 初始化底层TCP/IP堆栈
    ESP_ERROR_CHECK(esp_event_loop_create_default()); // 创建默认事件循环

    esp_netif_create_default_wifi_sta(); // 创建默认的WIFI STA。

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg); // 初始化WiFi为WiFi驱动程序
    wifi_sta_config_t cfg_sta = {
        .ssid = "black",
        .password = "black1234",
        .threshold.authmode = WIFI_AUTH_WPA2_PSK,   //加密方式
        .pmf_cfg = {
            .capable = true,
            .required = false
        },
    };
    esp_wifi_set_config(WIFI_IF_STA, (wifi_config_t *)&cfg_sta); // 设置ESP32 STA或AP的配置

    esp_wifi_set_mode(WIFI_MODE_STA); // 设置WiFi操作模式

    // 将事件处理程序的实例注册到默认循环中           任何事件
    esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL, NULL);
    // 将事件处理程序的实例注册到默认循环中            工作站从连接的AP获得IP事件
    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL, NULL);

    esp_wifi_start(); // 根据当前配置启动wifi

    xTaskCreate(&http_test_task, "http_test_task", 8192, NULL, 5, NULL); //问题点4: 这里参数需要设置足够大的栈大小, 否则会导致崩溃
}

修正后不崩溃的代码

百度网页返回的http结果太多了,会导致空间不够,
针对问题代码, 做出调整, 对栈空间大小做限制, 当http返回内容过长时,直接丢弃

#include <stdio.h>
#include <pthread.h>

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_wifi.h"
#include "esp_tls.h"
#include "esp_crt_bundle.h"
#include "esp_http_client.h"


static const char *TAG = "HTTP_REQUEST";
#define MAX_HTTP_OUTPUT_BUFFER 2048
#define HTTP_URL "http://www.baidu.com"

// HTTP 请求的处理函数
esp_err_t http_event_handler(esp_http_client_event_t *evt)
{
    // 缓存http响应的buffer
    static char *output_buffer;
    // 已经读取的字节数
    static int output_len;
    switch(evt->event_id) {
        case HTTP_EVENT_ERROR:
            ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
            break;
        case HTTP_EVENT_ON_HEADER:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
            break;
        case HTTP_EVENT_ON_DATA:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);

            if (!esp_http_client_is_chunked_response(evt->client)) {
                if (evt->user_data) {
                    // 这里对buffer长度进行判断, 如果http返回长度过长, 为防止溢出就丢弃,否则进行追加拷贝
                    int left = MAX_HTTP_OUTPUT_BUFFER - output_len -1;
                    if (left > evt->data_len)
                        memcpy(evt->user_data + output_len, evt->data, evt->data_len);
                    else if (left > 0)
                        memcpy(evt->user_data + output_len, evt->data, left);
                    else
                        ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, buffer full");
                } else {
                    // 如果实测user_data设置为空时,走这里申请堆内存会崩溃则可以注释掉这段,否则可以使用
                    if (output_buffer == NULL) {
                        output_buffer = (char *) malloc(esp_http_client_get_content_length(evt->client));
                        output_len = 0;
                        if (output_buffer == NULL) {
                            ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
                            return ESP_FAIL;
                        }
                    }
                    memcpy(output_buffer + output_len, evt->data, evt->data_len);
                }
                output_len += evt->data_len;
            }

            break;
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
            if (output_buffer != NULL) {
                // Response is accumulated in output_buffer. Uncomment the below line to print the accumulated response
                // ESP_LOG_BUFFER_HEX(TAG, output_buffer, output_len);
                free(output_buffer);
                output_buffer = NULL;
            }
            output_len = 0;
            break;
        case HTTP_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
            if (output_buffer != NULL) {
                free(output_buffer);
                output_buffer = NULL;
            }
            output_len = 0;
            break;
    }
    return ESP_OK;
}

void request(const char *url) {
    printf("request  -----------1\n");
    // 响应结果放在这里
    char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};

    // 创建一个 HTTP 客户端配置
    esp_http_client_config_t config = {
            .method = HTTP_METHOD_GET,
            .url = url,
            .event_handler = http_event_handler,
            .user_data = local_response_buffer,
            .disable_auto_redirect = true,
    };

    // 创建一个 HTTP 客户端并执行 GET 请求
    esp_http_client_handle_t client = esp_http_client_init(&config);
    printf("request  -----------2\n");
    esp_err_t err = esp_http_client_perform(client); // 请求百度网页时,一执行这行系统就会崩溃
    printf("request  -----------3\n");

    // 检查请求是否成功
    if (err == ESP_OK) {
        int len =  esp_http_client_get_content_length(client);
        ESP_LOGI(TAG, "Status = %d, content_length = %d",
                 esp_http_client_get_status_code(client),//状态码
                 len);//数据长度

    } else {
        printf("HTTP GET request failed: %s\n", esp_err_to_name(err));
    }
    printf("Response: %.*s\n", strlen(local_response_buffer), local_response_buffer);

    //断开并释放资源
    esp_http_client_cleanup(client);
    printf("request  -----------4\n");
}

void http_test_task(void *arg)
{
    sleep(15);
    request(HTTP_URL);

    vTaskDelete(NULL);
}

/**
 * @brief WiFi 的事件循环Handler
 * @param arg
 * @param event_base
 * @param event_id
 * @param event_data
 */
void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    printf("wifi_event_handler base:%s, id:%d\n", event_base, event_id);
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    {
        printf("esp_wifi_connect\n");
        esp_wifi_connect();
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        printf("esp_wifi_connect\n");
        esp_wifi_connect();
    }

    if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
        ESP_LOGI("ESP32", "IP地址:: " IPSTR, IP2STR(&event->ip_info.ip));

        //request(HTTP_URL); 问题点2: 获取到ip地址后,不要直接在这里执行http请求, 否则会直接崩溃 , 这里注释掉不用
    }
}

void app_main(void)
{
    esp_err_t ret = nvs_flash_init(); // 初始化默认NVS分区
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase()); // 擦除默认NVS分区
        ret = nvs_flash_init();             // 初始化默认NVS分区
    }
    ESP_ERROR_CHECK(ret);
    ESP_ERROR_CHECK(esp_netif_init());                // 初始化底层TCP/IP堆栈
    ESP_ERROR_CHECK(esp_event_loop_create_default()); // 创建默认事件循环

    esp_netif_create_default_wifi_sta(); // 创建默认的WIFI STA。

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg); // 初始化WiFi为WiFi驱动程序
    wifi_sta_config_t cfg_sta = {
        .ssid = "black",
        .password = "black1234",
        .threshold.authmode = WIFI_AUTH_WPA2_PSK,   //加密方式
        .pmf_cfg = {
            .capable = true,
            .required = false
        },
    };
    esp_wifi_set_config(WIFI_IF_STA, (wifi_config_t *)&cfg_sta); // 设置ESP32 STA或AP的配置

    esp_wifi_set_mode(WIFI_MODE_STA); // 设置WiFi操作模式

    // 将事件处理程序的实例注册到默认循环中           任何事件
    esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL, NULL);
    // 将事件处理程序的实例注册到默认循环中            工作站从连接的AP获得IP事件
    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL, NULL);

    esp_wifi_start(); // 根据当前配置启动wifi

    xTaskCreate(&http_test_task, "http_test_task", 8192, NULL, 5, NULL); //问题点3: 这里参数需要设置足够大的栈大小, 否则会导致崩溃, 可以根据实测来改, 最好MAX_HTTP_OUTPUT_BUFFER大,否则可能会崩溃.
}

这样连上wifi后, http get请求百度网页就正常了, 可以打印部分内容, 建议换成简单的页面的网址, 百度返回的数据太多了.

esp32相关文章

可见我的esp32专栏
作者:帅得不敢出门 csdn原创谢绝转载

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

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

相关文章

DDK拧紧控制器AFC1500维修_无法通讯问题怎么解决

‌DDK拧紧控制器在工业装配领域以其高效、精准的性能受到众多企业的青睐。特别是在汽车制造、航空航天、重型机械和其他需要大量螺栓紧固的行业。 ‌工具小巧 拧紧力范围广泛‌ 联网功能强大 配备扭矩和角度传感器 多回路控制器 一、检查电源及插头‌&#xff1a;首先应检…

2024公立医院绩效考核进行中,契约锁电子签章助力电子病历评级

2024年公立医院绩效考核正在进行中&#xff0c;由国家卫健委最新印发的《国家二级公立医院绩效考核操作手册&#xff08;2024版&#xff09;》以及《国家三级公立医院绩效考核操作手册&#xff08;2024版&#xff09;》将“电子病历应用功能水平分析应逐步提高”列为新增考核指…

【相似度计算 / 2】

题目 代码 #include <bits/stdc.h> using namespace std; unordered_set<string> s1, s2; int cnt1, cnt2, cnt; int n, m; void process(string& x) {for(char& c : x){if(c > a) continue;else c a - A;} } int main() {cin >> n >> m;…

加密软件的特殊功能有哪些

1.透明加密&#xff1a;在用户不感知的情况下自动对文件进行加密和解密&#xff0c;保证数据的安全性和使用的便捷性。 2.多种加密模式&#xff1a;提供多种加密模式&#xff0c;如透明加密、智能加密、只解密不加密等&#xff0c;满足不同场景下的数据保护需求。 3.应用加密…

基于协同过滤算法的电影推荐系统的设计与实现(论文+源码)_kaic

摘 要 现在观看电影已逐渐成为人们日常生活中最常见的一种娱乐方式&#xff0c;人们通常会在周末或在休息、吃饭时间不由自主地在各种视频软件中搜索当前火热的影视节目。但是现在的视频软件电影推荐功能不够完善&#xff0c;所以需要开发出一套系统来使用户只需要简单操作就能…

如何实现OpenHarmony的OTA升级

OTA简介 随着设备系统日新月异&#xff0c;用户如何及时获取系统的更新&#xff0c;体验新版本带来的新的体验&#xff0c;以及提升系统的稳定性和安全性成为了每个厂商都面临的严峻问题。OTA&#xff08;Over the Air&#xff09;提供对设备远程升级的能力。升级子系统对用户…

白嫖游戏指南,Epic喜加一:《野卡橄榄球》

前言 Epic喜加一&#xff1a;《野卡橄榄球》《野卡橄榄球》简介&#xff1a; 前言 接下来有时间会分享一些游戏相关可以白嫖的资源&#xff0c;包括游戏本体、游戏素材资源等等。 有需要的小伙伴可以关注这个专栏&#xff0c;不定期更新哦&#xff01; 专栏&#xff1a;白嫖…

微信小程序中Towxml解析Markdown及html

一、Towxml Towxml 是一个让小程序可以解析Markdown、HTML的解析库。 二、引入 2.1 clone代码 git clone https://github.com/sbfkcel/towxml.git2.2 安装依赖 npm install2.3 打包 npm run build2.4 引入文件 将dist文件复制到微信小程序根目录&#xff0c;改名为towx…

简化WPF开发:CommunityToolkit.Mvvm在MVVM架构中的实践与优势

文章目录 前言一、CommunityToolkit.Mvvm1.特点2.优点3.缺点 二、WPF项目应用1.引入到 WPF 项目2.使用示例 总结 前言 CommunityToolkit.Mvvm 是 Microsoft 提供的一个社区工具包&#xff0c;专为 MVVM&#xff08;Model-View-ViewModel&#xff09;模式设计&#xff0c;旨在帮…

基于Virtex UltraScale+ VU13P FPGA的4路FMC接口基带信号处理平台

Virtex UltraScale系列 FPGA处理器&#xff1a;XCVU13P-2FHGB2104I动态存储数量&#xff1a;2组DDR4 SDRAM动态存储容量&#xff1a;每组4GByte&#xff0c;每个颗粒为8GBit动态存储带宽&#xff1a;工作时钟1000MHz&#xff0c;数据率2000Mbps板载6路QSFP光纤接口板载4个FMC高…

echarts 柱状图_堆叠柱状图_数据分区_常用图表配置_数据可视化

Echarts 常用各类图表模板配置 注意&#xff1a; 这里主要就是基于各类图表&#xff0c;更多的使用 Echarts 的各类配置项&#xff1b; 以下代码都可以复制到 Echarts 官网&#xff0c;直接预览&#xff1b; 图标模板目录 Echarts 常用各类图表模板配置一、数据分区显示二、折…

Redis入门篇 - CentOS 7下载、安装Redis实操演示

文章记录了在CentOS 7上&#xff0c;通过源码的形式,下载安装Redis的操作过程 进入要安装Redis的目录 cd /usr/local下载源码压缩包 wget https://download.redis.io/redis-stable.tar.gz # 不同版本可能地址不同下载完成后&#xff0c;使用ll命令检查&#xff0c;可以看到下载…

移动端视频编辑SDK,赋能开发者,共创未来视界

美摄科技&#xff0c;作为移动端视频编辑领域的佼佼者&#xff0c;再次突破技术边界&#xff0c;推出了全面升级的移动端视频编辑SDK解决方案&#xff0c;旨在为广大开发者及内容创作者提供一套强大而灵活的创意工具箱&#xff0c;让视频与图片编辑的每一个细节都焕发无限可能。…

51单片机——定时器

1、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源&#xff0c;其电路的连接和运转均在单片机内部完成。 定时器作用: (1) 用于计时系统&#xff0c;可实现软件计时&#xff0c;或者使程序每隔一固定时间完成一项操作 (2) 替代长时间的Delay&#xff0c;提高…

LuaJit分析(三)luajit字节码文件格式

Luajit字节码文件格式的完整信息如上图所示&#xff0c;包括文件头Header和原型Proto&#xff0c;一个原型可以对应lua源码中的一个函数或源文件。一、文件头文件标志&#xff1a;占用三个字节&#xff0c;始终是0x1B4C4A&#xff0c;表示这是一个luajit文件版本&#xff1a;占…

006-Sleuth(Micrometer)+ZipKin分布式链路追踪

这里写目录标题 1 分布式链路追踪概述1.1 为什么会出现这个技术&#xff1f;需要解决哪些问题&#xff1f;1.2 在分布式与微服务场景下需要解决的问题 2 新一代Spring Cloud Sleuth&#xff1a;Micrometer2.1 官网重要提示2.1.1 新一代Sleuth2.1.2 官网2.1.3 说明2.1.3.1 老项目…

性能测试计划怎么写?

一&#xff0e;简介 简介部分就不用过多描述了&#xff0c;无非是项目的背景&#xff0c;进行此次性能测试的原因&#xff0c;以及性能测试覆盖的范围等等&#xff0c;几乎所有项目文档都在开端对项目进行简单的阐述。 二&#xff0e;性能测试需求 寻找的被测试对象和压力点…

SD-WAN 跨国专线主要应用在哪些地方?

随着企业需求的不断变化和发展&#xff0c;传统的WAN技术已无法完全满足现代企业的需求。因此&#xff0c;SD-WAN跨国专线逐渐成为企业连接全球业务的重要选择。SD-WAN跨国专线通过SD-WAN技术&#xff0c;实现跨国业务的高效专线连接&#xff0c;极大地提升了企业的全球运营能力…

泡泡玛特2024半年报发布:收入利润高增长 各项指标超预期

泡泡玛特发布2024上半年业绩报告。报告显示&#xff0c;2024年上半年泡泡玛特国际集团实现营收45.6亿元(人民币&#xff0c;下同)&#xff0c;同比增长62.0%&#xff0c;经调整后净利10.2亿元&#xff0c;同比增长90.1%。国内地市场差异化渠道定位及精细化运营驱动其业务实现营…

分类预测|基于Transformer-LSTM的数据分类预测Matlab程序 多特征输入多类别输出

分类预测|基于Transformer-LSTM的数据分类预测Matlab程序 多特征输入多类别输出 文章目录 一、Transformer-LSTM基本原理1. 模型原理TransformerLSTM 2. 流程步骤1. 数据预处理2. Transformer编码器3. LSTM层4. 分类层5. 模型训练与评估 3. 优势与应用 二、实验结果三、核心代码…