介绍

本文旨在介绍如何在使用Arduino内核的ESP32上创建一个简单的websocket客户端。我们将用它来联系一个远程测试websocket服务器。本ESP32教程的测试是使用集成在ESP32开发板中的DFRobot的ESP-WROOM-32设备进行的。

安装库文件

为了不必关注websocket协议的底层细节,我们将使用一个辅助库文件来帮助我们处理这些细节。

您可以点击此处查看库文件的GitHub页面。请注意,这是一个ESP8266库文件,在撰写本文时,ESP32还没有官方支持的库文件。尽管如此,通过一些更改,我们可以在ESP32上运行此库文件。

遗憾的是,Arduino IDE库管理器尚不提供此库文件。因此,我们需要手动安装。

为此,我们需要下载源代码,单击GitHub页面顶部“Clone or download(拷贝或下载)”按钮,然后单击“Download ZIP(下载压缩文件)”按钮即可获得源代码。图1中突出显示了这些按钮。

图1 - 从GitHub上下载库文件

在下载的“.zip”文件中有一个名为ESP8266-Websocket-master的文件夹。将此文件夹解压并重命名为ESP8266-Websocket。

现在,我们需要手动将解压和重命名的文件夹放在其他Arduino库文件的同一目录中。通常而言,这些库文件位于Windows用户文档(Documents)中名为Arduino的文件夹中。例如,在此示例中,库文件的存储地址为C: Users MyUsername Documents Arduino libraries。

在找到Arduino库文件夹后,只需将ESP8266-Websocket文件夹粘贴到其中即可。

在继续编程之前,我们需要更改ESP8266-Websocket文件夹中某些函数文件的名称。如果未执行这些更改,那么在尝试编译ESP32的代码时,我们将收到函数名称冲突导致的相关错误。

因此,为了避免该错误,我们需要接受ESP32论坛帖子中的一些建议。按照这些建议,我们需要打开ESP8266-Websocket文件夹中的MD5.c和MD5.h文件并重命名以下函数:

将MD5Init更改为MD5InitXXX

将MD5Update更改为MD5UpdateXXX

将MD5Final更改为MD5FinalXXX

请注意,函数名末尾的后缀XXX可以是其他内容,只要不使用原始名称就可以,使用原始名称会与其他定义相冲突。但无论怎样命名,我们都必须在.c和.h的文件中使用相同的新名称。

最后,保存更改并打开Arduino IDE,我们应该能够从该库中找到示例,如图2所示。

图2 - Arduino IDE上可用的库文件示例

接下来我们将分析以下代码,这些基于WebSocletClient_Demo的代码用于通过ESP32与服务器建立连接,我强烈建议您仔细了解一下WebSocletClient_Demo。其使用示例也可以从此处的GitHub页面获得。

全局变量和引用文件

我们将从导入一些库文件开始编写代码。首先,我们需要WiFi.h库文件,它用于连接WiFi网络。此外,我们还需要引用WebSocketClient.h库文件,以便可以访问连接服务器所需的所有函数。

#include #include 

接下来,我们将把连接WiFi网络所需的证书放入两个全局变量。网络名称(ssid)和密码是必需的信息。

const char* ssid = "YourNetworkName";const char* password = "YourNetworkPassword;

随后,我们需要指定连接的主机以及使用的URL路径。为简单起见,我们将使用在线回显 websocket服务器,它可以返回我们先前发送的内容。这样我们就可以测试我们的客户端,而无需自己设置websocket服务器。

因此,我们可将服务器主机设置为demos.kaazing.com,URL路径设置为/ echo。您可以点击此处测试此服务器。

char path[] = "/echo";char host[] = "demos.kaazing.com";

我们还需要一个WebSocketClient类对象,用于调用与服务器交互所需的函数。最后,我们需要一个WiFiClient类对象,用于在后台为WebSocketClient对象提供支持。

WebSocketClient webSocketClient;WiFiClient client;

setup函数

现在,我们将使用Arduino setup函数执行初始化任务。按照惯例,我们将首先建立一个串口连接以输出程序的结果。接下来,我们将把ESP32连接到一个WiFi网络。关于如何建立网络连接的详细信息,请参考先前的教程内容。

Serial.begin(115200);WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print(".");}Serial.println("");Serial.println("WiFi connected");Serial.println("IP address: ");Serial.println(WiFi.localIP());delay(5000);

在连接WiFi网络之后,我们将通过调用WiFiClient对象的connect方法与主机建立TCP连接。

此方法的第一个参数是一个字符串,它表示我们尝试访问的主机(我们在先前已将其声明为全局变量),第二个参数是正在侦听的端口编号。我们使用的测试服务器正在侦听端口80,即默认的HTTP端口。

我们还引用了对此连接尝试的错误检查程序。如果连接失败,程序将向串行端口打印一条消息,但程序仍将继续运行并最终失败。我们这样做是为了简化测试过程,因为我们处于受控的测试环境中。对于在实际应用中使用的弹性程序,我们应该引用更强大的错误检查程序,并在检测到错误时采取相应的措施。

if(client.connect(host, 80)) { Serial.println("Connected");}else { Serial.println("Connection failed.");}

接下来我们需要执行websocket handshake握手。可通过调用之前声明的WebSocketClient对象的handshake方法来完成握手。此方法的输入参数为WiFiClient对象,利用该对象与服务器通信。

如需了解更多关于握手期间的细节信息,可以点击此处查看源代码。重要的是,它将向服务器发送HTTP请求以升级websocket连接。

此升级很有必要,这是因为服务器可以利用websocket协议通过相同的端口与HTTP和websocket客户端进行通信[1]。因此,客户端需要指定通信对象为websocket。

在调用handshake方法之前,我们需要为WebSocketClient的路径和主机数据分配全局变量,这些先前定义的全局变量可用于表示主机及URL路径。

webSocketClient.path = path;webSocketClient.host = host;if (webSocketClient.handshake(client)) { Serial.println("Handshake successful");} else { Serial.println("Handshake failed.");}

完整的setup函数如下所示。

void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); delay(5000); if (client.connect(host, 80)) { Serial.println("Connected"); } else { Serial.println("Connection failed."); } webSocketClient.path = path; webSocketClient.host = host; if (webSocketClient.handshake(client)) { Serial.println("Handshake successful"); } else { Serial.println("Handshake failed."); }}

主循环

让我们开始编写主循环程序。现在,我们将编写程序向服务器发送和接收数据。首先,我们需要声明一个String类型的变量,该变量将用作从服务器接收的内容的数据缓冲区。

String data;

接下来,我们将检查客户端与服务器是否仍然处于连接状态。我们之前使用WiFiClient对象连接了服务器。 因此,我们将通过调用其connected方法检查连接状态是否正常,该方法不带参数,如果连接仍处于活动状态,则返回true,否则返回false。

在初始化WebSocketClient之后使用WiFiClient对象似乎很奇怪。我们可以将WebSocketClient视为WiFiClient上层的封装包,用于处理websocket协议的特定任务。因此,检查连接是否仍然可用是较低层级的函数,所以我们可以直接使用WiFiClient对象。

如果客户端与服务器仍然处于活跃状态,我们将向其发送一些数据。为此,我们只需调用WebSocketClient对象的sendData方法,将包含发送内容的字符串作为其输入参数。此函数的返回值为空(void)。

webSocketClient.sendData("Info to be echoed back");

如前所述,我们访问的服务器将简单地回显我们发送给它的数据。因此,我们可以从客户端获取数据,它应该与我们之前发送的内容完全匹配。

为了从服务器获取数据,我们调用了getData函数,将字符串缓冲区作为其输入参数,服务器的返回内容将被存放在此字符串缓冲区中。

webSocketClient.getData(data);

随后,如果返回内容的长度大于0,我们可以简单地打印出接收的数据。完整的主循环函数如下所示,其中包含了打印内容。请注意,在每次迭代主循环函数之前,我们还添加了一个小小的延迟。

void loop() { String data; if (client.connected()) { webSocketClient.sendData("Info to be echoed back"); webSocketClient.getData(data); if (data.length() > 0) { Serial.print("Received data: "); Serial.println(data); } } else { Serial.println("Client disconnected."); } delay(3000);}

最终代码

最终源代码如下所示。

#include #include const char* ssid = "YourNetworkName";const char* password = "YourNetworkPassword;char path[] = "/echo";char host[] = "demos.kaazing.com";WebSocketClient webSocketClient;WiFiClient client;void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); delay(5000); if (client.connect(host, 80)) { Serial.println("Connected"); } else { Serial.println("Connection failed."); } webSocketClient.path = path; webSocketClient.host = host; if (webSocketClient.handshake(client)) { Serial.println("Handshake successful"); } else { Serial.println("Handshake failed."); }}void loop() { String data; if (client.connected()) { webSocketClient.sendData("Info to be echoed back"); webSocketClient.getData(data); if (data.length() > 0) { Serial.print("Received data: "); Serial.println(data); } } else { Serial.println("Client disconnected."); } delay(3000);}

测试代码

为了测试此代码,只需编译并将其上传到ESP32即可。您将得到类似于图1的输出结果,发送至服务器的消息被返回并打印至串口控制台。

请注意,如果未按照“安装库文件”的说明重命名库函数,则无法编译ESP32代码。

图3 - 程序的输出结果

注:本文作者是Nuno Santos,他是一位和蔼可亲的电子和计算机工程师,住在葡萄牙里斯本 (Lisbon)。

他写了200多篇有关ESP32、ESP8266的有用的教程和项目。

ESP32教程大全: http://mc.dfrobot.com.cn/thread-271930-1-1.html

ESP32 tutorial:https://www.dfrobot.com/blog-964.html

c++ websocket客户端_ESP32 Arduino教程:Websocket客户端相关推荐

  1. esp32 micropython web服务器_ESP32 Arduino教程:Websocket server(服务器)

    本文主要介绍如何使用Arduino内核作为编程架构在ESP32(上创建Websocket server(服务器).所创建的Websocket server(服务器)将作为回发服务器使用,也就是说它会把 ...

  2. 串口监视软件_ESP32 Arduino教程:软件重置

    简介 该esp32 arduino教程旨在解释如何使用Arduino核心在ESP32开发板上执行软件重置. 本ESP32教程的测试是使用集成在ESP32开发板中的DFRobot的ESP-WROOM-3 ...

  3. Java Websocket实例【服务端与客户端实现全双工通讯】

    Java Websocket实例[服务端与客户端实现全双工通讯] 现很多网站为了实现即时通讯,所用的技术都是轮询(polling).轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发 出HTTP ...

  4. SpringBoot集成WebSocket案例:服务端与客户端消息互通

    pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...

  5. fleck 客户端_C# Fleck的WebSocket使用

    (1). Web网页端代码 WebSocket测试 .div1 { height:88px; width:173px; border:1px solid blue; margin:auto; } h4 ...

  6. websocket性能低?教你使用netty整合websocket(二)——实现点对点聊天(客户端与客户端通信)

    前提 了解如何实现客户端和服务端通讯 上一篇博客--SpringBoot+Netty整合websocket(一)--客户端和服务端通讯 实现点对点聊天 后端 1.建立服务端WebSocketNetty ...

  7. 石器时代linux架设教程,CentOS 6.5架设石器时代教程(客户端篇)

    [title]客户端篇[/title] 首先下载客户端 大亨石器客户端:https://pan.baidu.com/s/1R0fXmy6Fhyev5YUxcJ0pHQ  密码tj0u 第一步 配置客户 ...

  8. 微信群控的服务器怎么用,微信群控开发SDK使用教程--手机客户端返回聊天消息的原始内容给服务端...

    微信群控开发SDK使用教程--手机客户端返回聊天消息的原始内容给服务端 case RequestTalkContentTaskResultNotice: {// 返回聊天消息的原始内容 log.deb ...

  9. 虚拟机架设冒险岛服务器,冒险岛单机版V139虚拟机版+视频安装教程+139客户端+登录器...

    冒险岛单机版V139虚拟机版+视频安装教程+139客户端+登录器 步骤需要的文件: ① mxd_139_download.exe [这个是客户端下载器,打开会开始下载139客户端.] ② vm.rar ...

  10. 天龙八部修改服务器经验,端游【天龙八部万象归一服务端】万象量一第7版一键端架设客户端+详细修改教程...

    去掉之前的静态登录界面 添加新动态登录器场景同步官方桃花岛登录场景 客户端画质突破原来画质现在的客户端和之前的老客户端对比优美漂亮 重要更新改革换新添加游戏里面就可以替换附体和武魂外观不再需要使用附体 ...

最新文章

  1. 无需多个模型也能实现知识整合?港中文MMLab提出「烘焙」算法,全面提升ImageNet性能...
  2. Adaboost通俗易懂入门教程
  3. 碰上摩尔纹怎么办?这5招帮你解决!
  4. Numpy数组常用函数汇总(数学运算、三角函数、位运算、比较运算及其它)
  5. UWP入门(八)--几个简单的控件
  6. SAP UI5 that.getView().bindElement(that.Context)
  7. mysql数据库错误1317_请问为什么我的mysql数据库一直连接不上?两天了还没找到错误,请帮我看一下呀急急急...
  8. 原生js设置div隐藏或者显示_JavaScript动画方式控制div元素的隐藏和显示
  9. CentOS7 搭建Kafka消息队列环境,以及Python3操作Kafka Demo
  10. Python---列表与元组
  11. 最安全的金笛JDMail邮件系统的安全防范技术介绍--2
  12. oracle 11g rac进程起停
  13. 电视剧《都挺好》弹幕数据分析
  14. PHP+ffmpeg音频格式转化踩坑实录
  15. 网站优化策略有哪几种方法
  16. np.add.at和np.negative.at
  17. Latex 各种处理论文操作-插图、插表格
  18. 文件夹突然变成html文件,电脑上的几个文件夹突然变成了有exe扩展名的文件,这些文件夹打不开,怎么办?...
  19. 云计算和java开发哪个好找工作前景好,深入分析
  20. D. Omkar and Circle(非常有意思的一道题)

热门文章

  1. [极客]每个极客都应该知道的Linux技巧 (1)
  2. kvm : virsh create *** 报错处理
  3. C# 通过优酷网址 获取flash真实地址
  4. 转:从内部开始 认识Oracle数据库结构组件
  5. MYSQL生成日历表,通常在做报表的时候需要用来生成一个临时表,用来左连接等。...
  6. 笨办法学Python(learn python the hard way)--练习程序39-40
  7. .NetCore实践爬虫系统(一)解析网页内容
  8. java.lang.NoClassDefFoundError: org/junit/runner/manipulation/Filter
  9. javaweb实现教师和教室管理系统 java jsp sqlserver
  10. 图片处理应用:固定容器缩略图实现