WebSocket 实时双向通信

📅 2026-05-09 · 📂 硬件编程 · ⏱ 阅读约 7 分钟

📺 B站推荐视频:ESP32 入门教程

概述

HTTP 是"请求-响应"模式,客户端不问服务器就不说。WebSocket 则建立一个持久连接,服务器可以主动推送数据给客户端,实现真正的实时通信。

学习目标:理解 WebSocket 协议原理,用 ESPAsyncWebServer 搭建 WebSocket 服务,实现双向实时数据推送。

物料清单

WebSocket vs HTTP 对比

特性HTTPWebSocket
连接短连接(每次请求)长连接(一次握手)
方向客户端→服务器双向
延迟高(轮询开销)低(推送)
适用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 处理能力和网络带宽都有限。高频数据先在本地聚合再推送。