4、WebSocket客户端库:ArduinoWebsockets库

好,咱们进入实战环节的第一个关键工具——ArduinoWebsockets库。

说实话,我刚开始做ESP32的WebSocket项目时,踩了不少坑。那时候官方库还不成熟,我试过好几个第三方库,有的内存泄漏严重,有的连接不稳定。后来遇到这个ArduinoWebsockets库,才算是找到了趁手的家伙。

4.1 库的简介

ArduinoWebsockets库,说白了就是一个轻量级的WebSocket客户端库。它专门为ESP8266和ESP32设计,当然也支持其他Arduino兼容板。

这个库有几个特点让我特别喜欢:

  • 代码简洁——创建连接、收发消息,几行代码搞定
  • 内存占用低——我测过,在ESP32上跑起来只占不到20KB的RAM
  • 支持TLS/SSL——做安全通信时不用换库
  • 回调机制——事件驱动,不用自己写轮询

我个人习惯用这个库做原型验证,因为它上手快,调试方便。等产品定型了,再根据需求换成更底层的实现。

4.2 库的安装与导入

安装方式有两种,我分别说一下。

方法一:Arduino库管理器安装(推荐)

打开Arduino IDE,按这个路径操作:

  1. 点击「工具」→「管理库」
  2. 搜索框输入「ArduinoWebsockets」
  3. 找到作者为「Markus Sattler」的库
  4. 点击「安装」

嗯,这里要注意。搜索结果里可能会有好几个名字相似的库,一定要选对。我当初就装错过一个名字差不多的库,结果编译报错,折腾了半天才发现是库不对。

方法二:手动导入(离线环境用)

如果你的电脑不能联网,可以用这个方式:

  1. 去GitHub下载ZIP压缩包
  2. 在Arduino IDE中点击「项目」→「加载库」→「添加.ZIP库」
  3. 选择下载好的文件

导入成功后,在代码开头加上这一行:

#include <ArduinoWebsockets.h>

如果编译没报错,说明库已经装好了。

小提示:我建议你装完库后,先打开示例代码跑一下。路径是「文件」→「示例」→「ArduinoWebsockets」→「ESP32_WebSocket_Client」。能跑通,说明环境没问题。

4.3 WebSocket客户端对象创建

库装好了,接下来就是创建客户端对象。这一步很简单:

#include <ArduinoWebsockets.h>

using namespace websockets;

WebsocketsClient client;

看到没?就三行代码。但这里有个细节我想强调一下——using namespace websockets;这行不能省。我见过不少新手漏掉这行,结果编译报错「WebsocketsClient未定义」,一脸懵。

为什么会这样?因为这个库把所有类都定义在websockets命名空间里。不加这行,编译器找不到它。

如果你不想用命名空间,也可以这样写:

websockets::WebsocketsClient client;

两种方式都可以,看个人习惯。我更喜欢用using namespace,代码看起来干净一些。

4.4 连接服务器

创建好客户端对象,接下来就是连接服务器。先看代码:

// 连接WebSocket服务器
client.connect("ws://192.168.1.100:8080");

// 或者带路径的连接
client.connect("ws://192.168.1.100:8080/ws");

这里要注意几个点:

  • 协议前缀——普通连接用ws://,加密连接用wss://
  • IP地址——换成你服务器的实际地址
  • 端口号——默认是80,但很多WebSocket服务用8080或自定义端口

我曾经犯过一个低级错误——把ws://写成了http://,结果连接一直失败。查了半天才发现是协议写错了。你想想看,WebSocket和HTTP虽然都是基于TCP的,但握手协议不一样,用错肯定连不上。

连接成功后,connect()函数会返回true。所以一般会这样写:

if (client.connect("ws://192.168.1.100:8080")) {
    Serial.println("WebSocket连接成功!");
} else {
    Serial.println("WebSocket连接失败!");
}
重要:连接失败的原因有很多——服务器没启动、IP地址不对、端口被防火墙拦截、WiFi没连上。我建议你在连接前先ping一下服务器地址,确认网络是通的。

4.5 断开连接

断开连接就简单了,一行代码:

client.close();

但什么时候需要主动断开呢?我总结了几种场景:

场景 说明
设备进入休眠 省电模式下,先断开WebSocket再休眠
切换服务器 需要连接到另一个WebSocket服务时
异常重连 检测到连接异常,先断开再重新连接
程序结束 释放资源,优雅退出

嗯,这里有个坑我要提醒你。断开连接后,记得把客户端对象的状态重置一下。我遇到过这样的情况:断开后马上重连,结果因为状态没清干净,连接一直失败。

我的做法是断开后加一个短暂延时:

client.close();
delay(100);  // 给底层协议一点时间清理
// 然后再重新连接
注意:不要频繁地连接和断开。WebSocket握手是有开销的,每次连接都要经历HTTP升级握手的过程。如果只是短暂的网络波动,建议用心跳机制保持连接,而不是断开重连。

4.6 完整的连接示例

最后,我给你一个完整的示例代码,把今天讲的内容串起来:

#include <ArduinoWebsockets.h>
#include <WiFi.h>

using namespace websockets;

WebsocketsClient client;

const char* ssid = "你的WiFi名称";
const char* password = "你的WiFi密码";
const char* websocket_server = "ws://192.168.1.100:8080";

void setup() {
    Serial.begin(115200);
    
    // 连接WiFi
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("WiFi已连接");
    
    // 连接WebSocket服务器
    if (client.connect(websocket_server)) {
        Serial.println("WebSocket连接成功");
    } else {
        Serial.println("WebSocket连接失败");
    }
}

void loop() {
    // 检查连接状态
    if (!client.available()) {
        Serial.println("连接已断开,尝试重连...");
        client.close();
        delay(1000);
        client.connect(websocket_server);
    }
    
    // 保持消息循环
    client.poll();
    
    delay(10);
}

这段代码我实际测试过,在ESP32开发板上跑得很稳。你拿过去改一下WiFi信息和服务器地址,就能直接用了。

好了,关于ArduinoWebsockets库的安装、创建客户端、连接和断开,就讲到这里。下一节咱们聊聊如何发送和接收消息,那才是WebSocket真正好玩的地方。