ESP32S3内网实现 WebSocket
WebSocket 是一种网络通信协议,它提供了在单个 TCP 连接上进行全双工、双向通信的通道。它是为了在 Web 浏览器和服务器之间实现实时、高效的数据交换而设计的,是传统 HTTP 轮询技术的一种强大替代方案。
- 持久连接:
- 与 HTTP 请求不同(每个请求都需要建立和关闭连接),WebSocket 在客户端(如浏览器)和服务器之间建立一次连接,之后该连接会保持打开状态。
- 只要双方愿意,这个连接可以持续存在,允许数据在任何时候双向流动。
- 全双工通信:
- 一旦连接建立,客户端和服务器可以同时、独立地向对方发送数据。
- 服务器可以在有新信息时立即“推送”给客户端,无需客户端先发起请求。客户端也可以随时发送数据给服务器。
- 低开销:
- 建立连接时(通过一个特殊的 HTTP 握手过程),后续的数据交换使用非常轻量级的数据帧(frames) 进行传输。
- 相比于 HTTP 轮询(不断发送请求检查更新)或长轮询(挂起请求等待更新),WebSocket 大大减少了网络带宽消耗和延迟(尤其是往返延迟)。
- 基于事件驱动:
- 客户端和服务器端的代码通常基于事件模型编写。例如:
- 当连接成功建立时,触发 onopen 事件。
- 当收到对方发送的消息时,触发 onmessage 事件。
- 当连接关闭时,触发 onclose 事件。
- 当发生错误时,触发 onerror 事件。
- 握手过程:
- WebSocket 连接始于一个特殊的 HTTP 请求(称为“握手”)。这个请求包含一个 Upgrade: websocket 头,表明客户端希望将连接升级到 WebSocket 协议。
- 如果服务器支持 WebSocket,它会返回一个 HTTP 101(Switching Protocols)响应,同意升级协议。
- 握手成功后,初始的 HTTP 连接就被“升级”为 WebSocket 连接,后续的通信都使用 WebSocket 协议的数据帧进行,不再是 HTTP。
- 支持文本和二进制数据:
- WebSocket 可以高效地传输纯文本(如 JSON、XML)和二进制数据(如图片、音频、视频流、自定义协议数据)。
为什么需要 WebSocket? (对比 HTTP)
- HTTP 的局限性:
- 单向性: 传统 HTTP 是“请求-响应”模型。客户端发起请求,服务器返回响应。服务器无法主动向客户端推送数据。
- 高延迟: 实现“实时”效果(如聊天、游戏、实时数据更新)需要客户端不断轮询服务器(频繁发送请求询问是否有新数据),这会产生大量不必要的请求和显著的延迟。
- 高开销: 每个 HTTP 请求/响应都包含完整的 HTTP 头信息(如 cookies、user-agent 等),对于频繁的小数据更新来说,这些头部信息是巨大的开销。
- WebSocket 的优势:
- 真正的实时性: 服务器可以瞬间将新数据推送给所有连接的客户端。
- 低延迟: 省去了建立连接的开销和轮询的等待时间。
- 低带宽消耗: 连接建立后,数据传输帧的头部信息极小。
- 高效的双向通信: 适合需要频繁、快速交互的应用。
典型应用场景:
- 实时聊天应用: 消息的即时发送和接收。
- 在线多人游戏: 玩家动作和游戏状态的实时同步。
- 协作编辑工具: 多个用户同时编辑文档时的实时更新。
- 实时数据仪表盘: 股票行情、体育赛事比分、服务器监控、物联网设备数据流。
- 在线拍卖/博彩: 实时出价和结果更新。
- 基于位置的服务: 实时位置共享和更新。
- 社交网络实时通知。
关键点总结:
- 协议: WebSocket 是一个独立的协议 (ws:// 或加密的 wss://)。
- 连接: 持久、长连接。
- 通信模式: 全双工、双向。
- 效率: 低延迟、低开销。
- 目的: 实现 Web 应用和服务器的实时、高效双向通信。
简单来说: WebSocket 就像在浏览器和服务器之间打开了一条专用的电话线。一旦拨通(握手成功),双方可以随时说话(发送数据)和收听(接收数据),不需要反复拨号(建立连接),通话(数据传输)也非常高效。这使得构建实时交互性强的 Web 应用变得容易且高效。
通过ESP32S3实现,首先确认功能实现:
ESP32S3作为服务器配置成AP模式
客户端(手机,电脑)连接ESP32S3热点形成局域网(内网)
连接web界面展示:
menuconfig选项配置:
开启WebSocket 服务器支持
增大网址请求头长度
代码部分讲解:
从主函数入口就可以管中窥豹,从宏观看待流程- void app_main(void) {
- // 初始化非易失性存储器
- ESP_ERROR_CHECK(nvs_flash_init());
- // 初始化软AP模式
- wifi_init_softap();
- // 启动WebSocket服务器
- start_websocket_server();
- 初始化非易失性存储器
- 初始化软AP模式
- 启动WebSocket服务器
- }
复制代码 总共分三个部分
- 初始化非易失性存储器(NVS)
- 初始化软AP模式(配置ESP32S3为AP模式,配置内网传输环境)
- 启动WebSocket服务器(处理连接事件)
核心在第三部分,先处理客户端发起的http get请求,将其升级为WebSocket通信- // 启动WebSocket服务器
- static httpd_handle_t start_websocket_server(void) {
- // 声明一个httpd_handle_t类型的变量server,用于存储httpd_start函数返回的句柄
- httpd_handle_t server = NULL;
- // 声明一个httpd_config_t类型的变量config,用于存储httpd_start函数需要的配置参数
- httpd_config_t config = HTTPD_DEFAULT_CONFIG();
- // 设置uri匹配函数为httpd_uri_match_wildcard
- config.uri_match_fn = httpd_uri_match_wildcard;
- // 设置最大uri处理器的数量为16
- config.max_uri_handlers = 16;
- // 设置最大响应头的数量为16
- config.max_resp_headers = 16;
- // 设置最大打开的socket数量为4
- config.max_open_sockets = 4;
- // 调用httpd_start函数启动http服务器,并将返回的句柄存储在server变量中
- if (httpd_start(&server, &config) == ESP_OK) {
- // 声明一个httpd_uri_t类型的变量ws_uri,用于存储websocket的uri信息
- httpd_uri_t ws_uri = {
- .uri = "/ws",
- .method = HTTP_GET,
- .handler = ws_handler,//握手阶段,成功后升级通信协议为WebSocket
- .user_ctx = NULL,
- .is_websocket = true
- };
- httpd_register_uri_handler(server, &ws_uri);
- httpd_uri_t index_uri = {
- .uri = "/",
- .method = HTTP_GET,
- .handler = index_get_handler,//// 处理根路径的GET请求,发送html文件
- .user_ctx = NULL
- };
- httpd_register_uri_handler(server, &index_uri);
- }
- return server;
- }
复制代码 在这里服务器(ESP32S3)发送html网页文件给客户端,客户端在网页实现WebSocket接口调用
源码分享:
https://github.com/jianzhiji/blog/blob/main/ESP32S3_websocket.zip
结束语:
如果文章对你有所帮助,可以帮我点一下左下角推荐该文,万分感谢
博主目前在广州,深圳寻找找嵌入式软件实习。
如有大佬(HR,BOSS)能推荐实习,恳请私信小弟给个机会,帮帮小弟,万分感谢!!!
联系方式:博文侧边栏微信二维码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |