十四、【ESP32全栈开发指南:搭建轻量级HTTP服务器】

一、HTTP协议基础

HTTP(Hyper Text Transfer Protocol)作为互联网基础协议,采用请求-响应模型工作:

1.1 HTTP请求组成

GET /uri?query1=value1 HTTP/1.1      // 请求行(方法+URI+协议版本)
Host: example.com                   // 请求头(键值对)
User-Agent: curl/7.68.0
Accept: */*// 空行分隔
body_data...                        // 请求体(POST/PUT时存在)

1.2 HTTP响应结构

HTTP/1.1 200 OK                     // 状态行(版本+状态码+原因短语)
Content-Type: text/html             // 响应头
Content-Length: 123// 空行分隔
<html>...</html>                    // 响应体

常见状态码含义

状态码含义典型场景
200OK请求成功
301永久重定向网站改版
404Not FoundURI不存在
500服务器内部错误程序崩溃

二、ESP-HTTP-Server核心API

ESP-IDF提供轻量级HTTP服务器组件,核心接口如下:

2.1 服务器初始化

// 创建默认配置
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.server_port = 80;  // 设置监听端口// 启动HTTP服务器
httpd_handle_t server;
esp_err_t ret = httpd_start(&server, &config);

2.2 URI处理器注册

typedef struct {const char *uri;httpd_method_t method;esp_err_t (*handler)(httpd_req_t *r);void *user_ctx;
} httpd_uri_t;// 示例:注册GET处理器
httpd_register_uri_handler(server, &(httpd_uri_t){.uri = "/api/data",.method = HTTP_GET,.handler = data_get_handler,.user_ctx = NULL
});

2.3 请求解析关键API

函数功能描述
httpd_req_get_url_query_len()获取查询字符串长度
httpd_req_get_url_query_str()获取完整查询字符串
httpd_query_key_value()解析特定键值参数
httpd_req_recv()接收请求体数据

三、核心实现代码

3.1 GET请求处理

esp_err_t get_handler(httpd_req_t *req) {// 构造响应const char resp[] = "{\"status\":\"OK\",\"value\":25}";// 设置JSON类型响应头httpd_resp_set_type(req, "application/json");// 发送响应httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);return ESP_OK;
}

3.2 POST请求处理

esp_err_t post_handler(httpd_req_t *req) {char content[100];int recv_size = MIN(req->content_len, sizeof(content)-1);// 接收数据int ret = httpd_req_recv(req, content, recv_size);if (ret <= 0) {if (ret == HTTPD_SOCK_ERR_TIMEOUT) {httpd_resp_send_408(req);}return ESP_FAIL;}content[ret] = '\0';  // 添加字符串终止符// 处理接收的数据(示例:控制LED)if (strstr(content, "led=on")) {gpio_set_level(LED_GPIO, 1);}// 发送响应httpd_resp_send(req, "CMD_EXECUTED", 12);return ESP_OK;
}

3.3 URI处理器绑定

// GET端点配置
httpd_uri_t get_endpoint = {.uri = "/control",.method = HTTP_GET,.handler = get_handler,.user_ctx = NULL
};// POST端点配置
httpd_uri_t post_endpoint = {.uri = "/control",.method = HTTP_POST,.handler = post_handler,.user_ctx = NULL
};// 注册处理器
void register_handlers(httpd_handle_t server) {httpd_register_uri_handler(server, &get_endpoint);httpd_register_uri_handler(server, &post_endpoint);
}

四、实战应用示例

4.1 创建WiFi热点提供HTTP服务

void app_main() {// 初始化NVSnvs_flash_init();// 创建AP模式热点wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();esp_wifi_init(&cfg);wifi_config_t wifi_config = {.ap = {.ssid = "ESP32_AP",.password = "12345678",.max_connection = 4,.authmode = WIFI_AUTH_WPA_WPA2_PSK}};esp_wifi_set_mode(WIFI_MODE_AP);esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config);esp_wifi_start();// 启动HTTP服务器httpd_handle_t server = start_webserver();
}

4.2 关键功能测试方法

测试GET请求
curl "http://192.168.4.1/control?led=on"

响应示例:

{"status":"OK","value":1}
测试POST请求
curl -X POST -d "brightness=80" http://192.168.4.1/control

响应示例:

CMD_EXECUTED
实时调试输出
I (1254) HTTP_SERVER: Received 12 bytes: brightness=80
I (1256) GPIO: LED brightness set to 80%

4.3 动态URI管理

// 动态注销URI
httpd_unregister_uri(server, "/old_api");// 注册新URI
httpd_register_uri_handler(server, &(httpd_uri_t){.uri = "/new_api",.method = HTTP_GET,.handler = new_api_handler
});// 自定义错误处理
httpd_register_err_handler(server, HTTPD_404_NOT_FOUND, custom_404_handler);

五、进阶技巧

5.1 分块传输大文件

FILE *file = fopen("/spiffs/image.jpg", "rb");
const size_t CHUNK_SIZE = 1024;
uint8_t chunk[CHUNK_SIZE];while (fread(chunk, 1, CHUNK_SIZE, file) > 0) {httpd_resp_send_chunk(req, (char*)chunk, CHUNK_SIZE);
}
httpd_resp_send_chunk(req, NULL, 0);  // 结束传输
fclose(file);

5.2 安全增强方案

// Basic身份验证
char auth_header[150];
size_t auth_len = httpd_req_get_hdr_value_len(req, "Authorization");if (auth_len > 0) {httpd_req_get_hdr_value_str(req, "Authorization", auth_header, sizeof(auth_header));if (strstr(auth_header, "Basic dXNlcjpwYXNz") == NULL) {  // user:pass的base64httpd_resp_set_status(req, "401 Unauthorized");httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"ESP32\"");httpd_resp_send(req, NULL, 0);return ESP_OK;}
}

5.3 性能优化参数

httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.uri_match_fn = httpd_uri_match_wildcard;  // 启用通配符匹配
config.max_open_sockets = 6;       // 最大并发连接数
config.stack_size = 10240;         // 任务堆栈大小
config.lru_purge_enable = true;    // 启用LRU连接清理

六、常见问题排查

6.1 典型错误解决方案

错误现象可能原因解决方案
启动失败 (ESP_ERR_INVALID_ARG)端口被占用更换端口或重启设备
接收数据不完整缓冲区太小增大接收缓冲区
响应时间过长处理器阻塞优化处理逻辑或启用分块传输
OTA升级失败分区表配置错误检查分区表设置

6.2 调试技巧

// 启用详细日志
esp_log_level_set("httpd", ESP_LOG_VERBOSE);// 查看内存使用情况
ESP_LOGI(TAG, "Free heap: %d", esp_get_free_heap_size());// 网络抓包分析
// 使用Wireshark监听端口80流量

实测数据参考

  • 最小内存占用:~20KB RAM
  • 最大并发连接:6-8个(根据配置)
  • 请求处理延迟:<50ms(简单请求)

完整工程代码:GitHub仓库链接

参考资料

  1. ESP-IDF HTTP Server官方文档
  2. HTTP状态码详解

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

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

相关文章

java中LinkedList和ArrayList的区别和联系?

我们被要求解释Java中LinkedList和ArrayList的区别和联系。下面将分别从实现原理、性能特点、使用场景等方面进行详细说明&#xff0c;并总结它们的相同点和不同点。 # 一、联系&#xff08;共同点&#xff09; 1. 都实现了List接口&#xff0c;因此具有List接口的所有方法&…

明远智睿SD2351核心板:边缘计算时代的工业级核心引擎深度解析

在工业4.0与物联网深度融合的背景下&#xff0c;边缘计算设备正从单一功能模块向高集成度、智能化平台演进。明远智睿推出的SD2351核心板&#xff0c;凭借其异构计算架构、工业级接口资源和全栈技术生态&#xff0c;重新定义了边缘计算设备的性能边界。本文将从技术架构、场景适…

Flask 动态模块注册

目录 1. 项目概述2. 项目结构3. 核心组件解析3.1 动态模块注册系统 (api/__init__.py)3.2 应用程序入口 (setup_demo.py) 4. 模块开发指南4.1 标准模块 (*_app.py)4.2 SDK模块 (sdk/*.py) 5. URL路径规则6. 如何使用6.1 启动应用6.2 添加新模块 7. 工作原理 1. 项目概述 这个项…

JVM 内存、JMM内存与集群机器节点内存的联系

目录 1、JVM 内存 1.1、分配机制 1.2、jvm模型位置 1.3、字节码内存块 2、JMM内存 2.1、JMM模型 2.2、工作流程图 1、工作内存与主内存的交互 2. 多线程下的主内存与堆内存交互 2.3、 主内存与工作内存的同步方案 1、volatile 2、synchronized 3、final 3、内存使…

学习昇腾开发的第一天--环境配置

1、昇腾社区官网&#xff1a;昇腾社区官网-昇腾万里 让智能无所不及 2、产品-->选择开发者套件-->点击制卡工具的下载&#xff1a;资源-Atlas 200I DK A2-昇腾社区 3、如果制卡工具不能使用在线制卡&#xff0c;可以下载镜像到本地使用本地制卡&#xff1a;Linux系统制…

Android WebView 深色模式适配方案总结

Android WebView 深色模式适配方案总结 在 Android WebView 中适配深色模式&#xff08;Dark Mode&#xff09;是一个常见的需求&#xff0c;尤其是当加载的网页没有原生支持 prefers-color-scheme 时。本文将介绍 3 种主流方案&#xff0c;并分析它们的优缺点&#xff0c;帮助…

项目练习:使用mybatis的foreach标签,实现union all的拼接语句

文章目录 一、需求说明二、需求分析三、代码实现四、报表效果 一、需求说明 在sql查询数据后&#xff0c;对数据分组统计。并最后进行总计。 二、需求分析 最终&#xff0c;我想用sql来实现这个统计和查询的功能。 那么&#xff0c;怎么又查询&#xff0c;又统计了&#xf…

7.7 Extracting and saving responses

Chapter 7-Fine-tuning to follow instructions 7.7 Extracting and saving responses 在本节中&#xff0c;我们保存测试集响应以便在下一节中评分&#xff0c;除此之外保存模型的副本以供将来使用。 ​ 首先&#xff0c;让我们简单看看finetuned模型生成的响应 torch.manu…

计算机网络第3章(上):数据链路层全解析——组帧、差错控制与信道效率

目录 一、数据链路层的功能二、组帧2.1 字符计数法&#xff08;Character Count&#xff09;2.2 字符填充法&#xff08;Character Stuffing&#xff09;2.3 零比特填充法2.4 违规编码法 三、差错控制3.1 检错编码&#xff08;奇偶校验码&#xff09;3.2 循环冗余校验&#xff…

铸铁试验平台的重要性及应用前景

铸铁作为一种重要的金属材料&#xff0c;在工业生产中扮演着举足轻重的角色。为了确保铸铁制品的质量和性能&#xff0c;铸铁材料的试验是必不可少的环节。而铸铁试验平台则是进行铸铁试验的关键设备之一&#xff0c;它为铸铁材料的研究和开发提供了重要的技术支持。本文将探讨…

std::shared_ptr引起内存泄漏的例子

目录 一、循环引用&#xff08;最常见场景&#xff09; 示例代码 内存泄漏原因 二、共享指针管理的对象包含自身的 shared_ptr 示例代码 内存泄漏&#xff08;或双重释放&#xff09;原因 三、解决方案 1. 循环引用&#xff1a;使用 std::weak_ptr 2. 对象获取自身的 …

AI 知识数据库搭建方案:从需求分析到落地实施

AI 知识数据库的搭建需结合业务场景、数据特性与技术架构&#xff0c;形成系统化解决方案。以下是一套完整的搭建框架&#xff0c;涵盖规划、设计、实施及优化全流程&#xff1a; 一、前期规划&#xff1a;需求分析与目标定义 1. 明确业务场景与知识需求 场景导向&#xff1a…

Tensorflow 基础知识:变量、常量、占位符、Session 详解

在深度学习领域,TensorFlow 是一个广泛使用的开源机器学习框架。想要熟练使用 TensorFlow 进行模型开发,掌握变量、常量、占位符和 Session 这些基础知识是必不可少的。接下来,我们就深入了解一下它们的概念、用处,并通过代码示例进行演示。 一、常量(Constant) 常量,顾…

linux 常见问题之如何清除大文件的内容

linux 常见问题之如何清除大文件的内容 在 Linux 系统中&#xff0c;我们有时会遇到文件随着时间增长变得巨大&#xff0c;最常见的就是服务器的日志文件&#xff0c;随着时间的推移占用大量的磁盘空间&#xff0c;下面介绍如何清楚大文件的内容&#xff0c;当然避免文件内容过…

薛定谔的猫思想实验如何推演到量子计算

前言 这是我的选修课作业&#xff0c;但是我并不喜欢小论文方式的写法&#xff0c;死板又老套。先在这打一份底稿。 薛定谔的猫 可能一说到量子这个关键词&#xff0c;大家第一时间都会想到的是“薛定谔的猫”。 实验介绍 薛定谔的猫是一个著名的思想实验&#xff0c;由奥…

嵌入式开发中fmacro-prefix-map选项解析

在嵌入式开发中&#xff0c;-fmacro-prefix-map 是 GCC 和 Clang 等编译器提供的一个路径映射选项&#xff0c;主要用于在预处理阶段重写宏定义中出现的绝对路径。它的核心目的是解决以下问题&#xff1a; 核心作用 构建可重现性 消除编译输出&#xff08;如 .o、.d 文件&…

Javaweb学习——day3(Servlet 中处理表单数据)

文章目录 一、概念学习1. GET vs POST 请求方式的区别2. HttpServletRequest 获取表单数据 二、代码讲解与练习第 1 步&#xff1a;在 webapp 下创建 login.html第 2 步&#xff1a;在 com.example 包下创建 LoginServlet第 3 步&#xff1a;修改 web.xml 注册 LoginServlet第 …

在 iOS 开发中单独解析域名为 IP

1 为什么要自己解析? 典型场景说明劫持/污染检测比较 系统解析 与 自建 DNS 的差异QoS / CDN 选路对每个候选 IP 做 RT/丢包测速系统 API(NSURLSession / Network.framework)在「真正建立连接之前」不会把解析结果暴露出来,因此需要主动解析一步。 2 API 选型概览 API是否过…

YOLOv1 技术详解:正负样本划分与置信度设计

&#x1f50d; YOLOv1 技术详解&#xff1a;正负样本划分与置信度设计 一、前言 YOLOv1 是目标检测领域中具有划时代意义的算法之一&#xff0c;它将检测任务统一为一个回归问题&#xff0c;实现了“You Only Look Once”的端到端实时检测。其中&#xff0c;正负样本的划分机…

为 Nginx 配置 HTTPS(以 n8n 为例)完整教程【CentOS 7】

在部署如 n8n 这类自动化平台时&#xff0c;为了保障数据传输安全&#xff0c;我们通常会使用 HTTPS 访问。本文将以 n8n.example.com 为例&#xff0c;介绍如何在 CentOS 7 系统中通过 Nginx 为本地运行在端口 5678 的 n8n 服务配置免费 SSL 证书&#xff08;Let’s Encrypt&a…