WebSocket 实时双向通信
📅 2026-05-09 · 📂 硬件编程 · ⏱ 阅读约 7 分钟
概述
HTTP 是"请求-响应"模式,客户端不问服务器就不说。WebSocket 则建立一个持久连接,服务器可以主动推送数据给客户端,实现真正的实时通信。
学习目标:理解 WebSocket 协议原理,用 ESPAsyncWebServer 搭建 WebSocket 服务,实现双向实时数据推送。
物料清单
- ESP32 ×1
- 电位器(模拟传感器输入)×1
- 面包板+杜邦线
WebSocket vs HTTP 对比
| 特性 | HTTP | WebSocket |
|---|
| 连接 | 短连接(每次请求) | 长连接(一次握手) |
| 方向 | 客户端→服务器 | 双向 |
| 延迟 | 高(轮询开销) | 低(推送) |
| 适用 | REST API | 实时仪表盘、聊天 |
实战:实时传感器数据推送
// WebSocket_Push.ino — 实时推送ADC数据
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
void onWsEvent(AsyncWebSocket *s, AsyncWebSocketClient *c, AwsEventType t, void *arg, uint8_t *data, size_t len) {
if (t == WS_EVT_CONNECT) Serial.printf("客户端#%u 已连接
", c->id());
if (t == WS_EVT_DATA) {
// 收到客户端消息,可做控制指令解析
Serial.printf("收到: %s
", (char*)data);
}
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(500);
ws.onEvent(onWsEvent);
server.addHandler(&ws);
// 内嵌网页:用JS WebSocket接收实时数据
server.on("/", HTTP_GET, [](AsyncWebServerRequest *r){
r->send(200, "text/html", "网页HTML(见解释)");
});
server.begin();
}
void loop() {
// 每100ms推送一次ADC值给所有连接的客户端
static unsigned long last = 0;
if (millis() - last > 100) {
last = millis();
char buf[64];
sprintf(buf, "{"adc":%d,"v":%.2f}", analogRead(34), analogRead(34)*3.3/4095.0);
ws.textAll(buf);
}
}
前端 JS 代码(嵌入式网页)
// 放在 setup() 的 HTML 字符串里
<script>
const ws = new WebSocket(`ws://${location.host}/ws`);
ws.onmessage = (e) => {
const d = JSON.parse(e.data);
document.getElementById('adc').innerText = d.adc;
document.getElementById('volt').innerText = d.v;
};
</script>
常见问题
⚠️ 内存泄漏:客户端频繁连接/断开时注意清理 AsyncWebSocketClient 资源。长时间运行可用 ws.cleanupClients() 定期清理死连接。
💡 延迟优化:推送间隔不要小于 50ms,ESP32 处理能力和网络带宽都有限。高频数据先在本地聚合再推送。