一、HTTP服务器基础
1.1 什么是HTTP服务器?
HTTP服务器是能够处理HTTP请求并返回响应的网络服务程序。在物联网应用中,ESP32可以作为轻量级HTTP服务器,直接接收来自客户端(如浏览器、手机APP)的请求。
1.2 ESP32作为HTTP服务器的特点
-
轻量级:适合资源有限的嵌入式设备
-
低功耗:可作为电池供电设备的控制接口
-
本地网络服务:无需云端即可提供Web服务
-
实时交互:直接控制硬件设备
-
配置简单:无需复杂网络配置
1.3 典型应用场景
-
设备控制面板:通过网页控制LED、继电器等
-
传感器数据展示:实时显示温湿度等数据
-
设备配置界面:WiFi配置、参数设置
-
OTA升级服务:本地固件更新
-
局域网IoT中心:聚合多个设备数据
二、ESP32-S3 HTTP服务器实现 (FreeRTOS + Arduino框架)
#include <WiFi.h>
#include <WebServer.h>
#include <ArduinoJson.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
// WiFi配置
const char* ssid = "Your_WiFi_SSID";
const char* password = "Your_WiFi_Password";
// 创建WebServer实例,监听80端口
WebServer server(80);
// FreeRTOS任务句柄
TaskHandle_t webServerTaskHandle = NULL;
// 传感器数据示例
float temperature = 25.0;
float humidity = 60.0;
// 处理根路径请求
void handleRoot() {String html = "<!DOCTYPE html><html><head>";html += "<title>ESP32 Web Server</title>";html += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">";html += "<style>body{font-family:Arial;text-align:center;margin-top:50px;}";html += ".card{display:inline-block;width:150px;border-radius:10px;";html += "box-shadow:0 4px 8px 0 rgba(0,0,0,0.2);padding:20px;margin:10px;}";html += ".button{padding:10px 20px;background-color:#4CAF50;color:white;";html += "border:none;border-radius:5px;text-decoration:none;}</style></head>";html += "<body><h1>ESP32 Web Server</h1>";// 显示传感器数据html += "<div class=\"card\"><h3>Temperature</h3><p>" + String(temperature) + " °C</p></div>";html += "<div class=\"card\"><h3>Humidity</h3><p>" + String(humidity) + " %</p></div>";// 控制按钮html += "<div style=\"margin-top:30px;\">";html += "<a href=\"/led_on\" class=\"button\">LED ON</a> ";html += "<a href=\"/led_off\" class=\"button\">LED OFF</a>";html += "</div></body></html>";server.send(200, "text/html", html);
}
// 处理LED控制请求
void handleLEDOn() {digitalWrite(LED_BUILTIN, HIGH);server.send(200, "text/plain", "LED is ON");
}
void handleLEDOff() {digitalWrite(LED_BUILTIN, LOW);server.send(200, "text/plain", "LED is OFF");
}
// 处理API数据请求
void handleAPI() {StaticJsonDocument<200> jsonDoc;jsonDoc["device"] = "ESP32-S3";jsonDoc["temperature"] = temperature;jsonDoc["humidity"] = humidity;jsonDoc["uptime"] = millis() / 1000;String response;serializeJson(jsonDoc, response);server.send(200, "application/json", response);
}
// 处理未找到的路径
void handleNotFound() {String message = "File Not Found\n\n";message += "URI: ";message += server.uri();message += "\nMethod: ";message += (server.method() == HTTP_GET) ? "GET" : "POST";message += "\nArguments: ";message += server.args();message += "\n";for (uint8_t i = 0; i < server.args(); i++) {message += " " + server.argName(i) + ": " + server.arg(i) + "\n";}server.send(404, "text/plain", message);
}
// Web服务器任务
void webServerTask(void *pvParameters) {while (1) {server.handleClient();vTaskDelay(10 / portTICK_PERIOD_MS);}
}
void setup() {Serial.begin(115200);pinMode(LED_BUILTIN, OUTPUT);// 连接WiFiWiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(".");}Serial.println("");Serial.println("WiFi connected");Serial.print("IP address: ");Serial.println(WiFi.localIP());// 配置路由server.on("/", handleRoot);server.on("/led_on", handleLEDOn);server.on("/led_off", handleLEDOff);server.on("/api", handleAPI);server.onNotFound(handleNotFound);// 启动Web服务器server.begin();Serial.println("HTTP server started");// 创建Web服务器任务xTaskCreatePinnedToCore(webServerTask, // 任务函数"WebServer Task", // 任务名称8192, // 堆栈大小NULL, // 参数1, // 优先级&webServerTaskHandle, // 任务句柄1 // 运行在核心1上);
}
void loop() {// 模拟更新传感器数据temperature = 25.0 + (millis() % 200) * 0.1;humidity = 60.0 + (millis() % 150) * 0.1;vTaskDelay(10000 / portTICK_PERIOD_MS); // 每10秒更新一次
}
2.1 代码说明
-
WebServer初始化:
-
使用
WebServer
类创建服务器实例 -
默认监听80端口(HTTP标准端口)
-
-
路由处理:
-
server.on()
注册路径处理函数 -
支持静态页面和API接口
-
处理GET/POST请求
-
-
HTML生成:
-
动态生成响应页面
-
包含CSS内联样式
-
响应式设计适配移动设备
-
-
JSON API:
-
使用ArduinoJson库生成JSON数据
-
返回设备状态和传感器数据
-
-
多任务处理:
-
使用FreeRTOS单独处理Web请求
-
避免阻塞主循环
-
2.2 使用说明
-
修改WiFi配置(
ssid
和password
) -
根据需求添加更多路由处理
-
集成实际传感器读取代码
-
如需HTTPS支持需额外配置
2.3 所需库
-
WiFi.h (Arduino ESP32核心自带)
-
WebServer.h (Arduino ESP32核心自带)
-
ArduinoJson.h (需单独安装)
三、功能验证与测试
3.1 基础功能测试
-
上传代码后,查看串口输出的IP地址
-
在浏览器中输入
http://[ESP32-IP]
-
应显示包含传感器数据和控制按钮的页面
-
点击LED控制按钮测试功能
-
访问
http://[ESP32-IP]/api
测试JSON API
3.2 高级测试场景
3.2.1 使用cURL测试API
# 获取设备信息
curl http://[ESP32-IP]/api
# 控制LED
curl http://[ESP32-IP]/led_on
curl http://[ESP32-IP]/led_off
3.2.2 POST请求测试
添加表单处理路由:
void handleForm() {if (server.method() != HTTP_POST) {server.send(405, "text/plain", "Method Not Allowed");return;}String message = "Received:\n";for (uint8_t i = 0; i < server.args(); i++) {message += server.argName(i) + ": " + server.arg(i) + "\n";}server.send(200, "text/plain", message);
}
// 在setup()中添加
server.on("/submit", HTTP_POST, handleForm);
测试命令:
curl -X POST -d "name=ESP32&value=100" http://[ESP32-IP]/submit
四、实际项目应用
4.1 智能家居控制面板
// 控制多个设备的HTML页面
void handleControlPanel() {String html = "<html><body><h1>Home Control</h1>";html += "<form action='/control' method='post'>";html += "Light: <input type='radio' name='light' value='1'>ON ";html += "<input type='radio' name='light' value='0' checked>OFF<br>";html += "Fan Speed: <input type='range' name='fan' min='0' max='3'><br>";html += "<input type='submit' value='Apply'>";html += "</form></body></html>";server.send(200, "text/html", html);
}
// 处理控制请求
void handleControl() {if (server.hasArg("light")) {int lightState = server.arg("light").toInt();digitalWrite(LIGHT_PIN, lightState);}if (server.hasArg("fan")) {int fanSpeed = server.arg("fan").toInt();analogWrite(FAN_PIN, fanSpeed * 85);}server.send(200, "text/plain", "Settings applied");
}
4.2 OTA升级服务
#include <Update.h>
void handleOTAUpdate() {server.sendHeader("Connection", "close");server.send(200, "text/html", "<form method='POST' action='/do_update' enctype='multipart/form-data'>""<input type='file' name='update'>""<input type='submit' value='Update'>""</form>");
}
void handleDoUpdate() {HTTPUpload& upload = server.upload();if (upload.status == UPLOAD_FILE_START) {Serial.printf("Update: %s\n", upload.filename.c_str());if (!Update.begin(UPDATE_SIZE_UNKNOWN)) {Update.printError(Serial);}} else if (upload.status == UPLOAD_FILE_WRITE) {if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {Update.printError(Serial);}} else if (upload.status == UPLOAD_FILE_END) {if (Update.end(true)) {Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);server.sendHeader("Location", "/");server.send(303);} else {Update.printError(Serial);}}
}
// 在setup()中添加
server.on("/update", handleOTAUpdate);
server.on("/do_update", HTTP_POST, []() {server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");ESP.restart();
}, handleDoUpdate);
五、性能优化与安全
5.1 性能优化技巧
-
使用SPIFFS存储静态文件
#include <SPIFFS.h> void setup() {if(!SPIFFS.begin(true)){Serial.println("SPIFFS Mount Failed");return;}server.serveStatic("/", SPIFFS, "/index.html"); }
-
启用Gzip压缩
server.enableCORS(true); server.enableGzip();
-
连接复用
server.setReusePort(true);
5.2 安全增强措施
-
基本认证
server.requireAuthentication("admin", "password");
-
HTTPS支持
#include <HTTPSServer.hpp> using namespace httpsserver; // 需要加载证书和私钥 HTTPSServer secureServer = HTTPSServer(443);
-
请求限制
void handleRequest() {static unsigned long lastRequest = 0;if (millis() - lastRequest < 1000) {server.send(429, "text/plain", "Too Many Requests");return;}lastRequest = millis();// 正常处理 }
六、扩展功能
6.1 WebSocket实时通信
#include <WebSocketsServer.h>
WebSocketsServer webSocket = WebSocketsServer(81);
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {switch(type) {case WStype_DISCONNECTED:Serial.printf("[%u] Disconnected!\n", num);break;case WStype_CONNECTED:Serial.printf("[%u] Connected!\n", num);break;case WStype_TEXT:Serial.printf("[%u] Received: %s\n", num, payload);webSocket.broadcastTXT(payload, length);break;}
}
void setup() {webSocket.begin();webSocket.onEvent(webSocketEvent);
}
6.2 mDNS服务发现
#include <ESPmDNS.h>
void setup() {if (MDNS.begin("esp32")) {Serial.println("mDNS responder started");MDNS.addService("http", "tcp", 80);}
}
七、总结与扩展学习
7.1 学习路径
-
进阶Web开发
-
学习使用SPIFFS文件系统
-
实现更复杂的前端界面
-
添加WebSocket实时通信
-
-
安全增强
-
实现HTTPS安全连接
-
添加用户认证系统
-
防止CSRF攻击
-
-
性能优化
-
学习异步Web服务器
-
实现缓存策略
-
优化内存使用
-
7.2 相关资源推荐
-
ESP32开发入门(七):HTTP客户端开发实践
-
ESP32官方WebServer示例
-
ArduinoJson文档
-
ESP32 HTTPS服务器指南