我使用以下Arduino websocket library,在尝试发送超过65535个字符的邮件时出现问题,我遇到了握手失败错误。
只要消息不超过这个长度,它就能完美地运行
图书馆的主要网页上有一条说明:
Because of limitations of the current Arduino platform (Uno at the time of this writing),
this library does not support messages larger than 65535 characters.
In addition, this library only supports single-frame text frames.
It currently does not recognize continuation frames, binary frames, or ping/pong frames.
在名为 WebSocketClient.h 的客户端头文件中,有以下注释:
// Don't allow the client to send big frames of data. This will flood the arduino memory and might even crash it.
#ifndef MAX_FRAME_LENGTH
#define MAX_FRAME_LENGTH 256
#endif
我正在使用这个旧库,因为它是我Arduino WIFI shield上唯一一个为我工作的库,我无法找到支持WiFi屏蔽的其他库,因为大多数的webscket库都是写的Arduino Eathernet Shield支持,我没有。
我的Arduino代码
/*DS18 Libs*/
#include <dht.h>
#include <OneWire.h>
#include <DallasTemperature.h>
/*Websocket Libs*/
#include <WebSocketServer.h>
#include <WebSocketClient.h>
#include <sha1.h>
#include <MD5.h>
#include <global.h>
#include <Base64.h>
#include <SPI.h>
#include <WiFiUdp.h>
#include <WiFiServer.h>
#include <WiFiClient.h>
#include <WiFi.h>
#include <string.h>
char ssid[] = "AMM";
char pass[] = "027274792";
int status = WL_IDLE_STATUS;
IPAddress server(192, 168, 1, 3);
WiFiClient WiFiclient;
WebSocketClient WSclient;
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
//Humidture
dht DHT;
#define DHT11_PIN 4
void setup()
{
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
//check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network");
/* Connect to the websocket server*/
if (WiFiclient.connect(server, 8080)) {
Serial.println("Connected");
}
else {
Serial.println("Connection failed.");
while (1) {
// Hang on failure
}
}
// Handshake with the server
WSclient.path = "/MyServer/endpoint/testtest/device/d6220ae7-caa9-48b5-92db-630c4c296ec4";
WSclient.host = "192.168.1.3:8080";
if (WSclient.handshake(WiFiclient)) {
Serial.println("Handshake successful");
}
else {
Serial.println("Handshake failed.");
while (1) {
// Hang on failure
}
}
/*DS18*/
sensors.begin();
}
void loop()
{
WSclient.sendData("{\"service_code\":\"89c4da72-a561-47db-bf62-8e63f8c4bbf0\",\"data\":[" + getHumidtureValue() + "],\"service_type\":\"TemperatureHumidityAnalysis\"}");
WSclient.sendData("{\"service_code\":\"bdc0f984-6550-4712-881f-b09071da5a73\",\"data\":" + getCBodyTempretureValue() + ",\"service_type\":\"TemperatureGaugeMonitor\"}");
//line-3 commented WSclient.sendData("{\"service_code\":\"8c212432-a86e-4c18-a956-9dc0dbb648d4\",\"data\":[" + getHumidtureValue() + "],\"service_type\":\"HumidityGaugeMonitor\"}");
}
String getCBodyTempretureValue()
{
sensors.requestTemperatures(); // Send the command to get temperatures
char charVal[10];
return dtostrf(sensors.getTempCByIndex(0), 4, 2, charVal);
}
String getHumidtureValue()
{
String str = "";
for (int i = 0; i < 2; i++)
{
int chk = DHT.read11(DHT11_PIN);
switch (chk)
{
case DHTLIB_OK:
Serial.println("OK,\t");
break;
case DHTLIB_ERROR_CHECKSUM:
Serial.println("Checksum error,\t");
break;
case DHTLIB_ERROR_TIMEOUT:
Serial.println("Time out error,\t");
break;
default:
Serial.println("Unknown error,\t");
break;
}
char charVal[10];
double tempF = (DHT.temperature * 9) / 5 + 32;
str = dtostrf(tempF, 3, 1, charVal);
str = str + "," + dtostrf(DHT.humidity, 3, 1, charVal);
Serial.println(str);
delay(200);
}
return str;
}
上面的代码工作正常,当我取消注释循环函数中的第三个发送语句时,我得到了握手失败错误。
- 为新版本的Arduino板修改 MAX_FRAME_LENGTH 的值是否安全,考虑到这个库是旧库?
- 有没有比这个更好的其他库可以支持WiFi屏蔽上的websocket?
任何解决方案或想法都会受到赞赏。
提前致谢。
答案 0 :(得分:0)
在没有查看库的代码的情况下,更改最大帧长度可能不安全,因为websocket protocol根据有多长时间对有效负载长度进行不同的编码:
有效载荷长度:7位,7 + 16位或7 + 64位。
&#34;有效载荷数据&#34;的长度,以字节为单位:如果为0-125,则为有效载荷长度。如果为126,则后面的2个字节被解释为16位无符号整数,即有效负载长度。如果为127,则后面的8个字节被解释为64位无符号整数(最高有效位必须为0)是有效载荷长度。
当库表示它不支持65535字节以上的有效载荷长度时,可能意味着它没有实现64位长度编码。
答案 1 :(得分:0)
经过多次试验,很多次程序行为非常奇怪,这让我发疯,我发现问题是我在程序中使用太多字符串,这使得Arduino-Uno很容易耗尽RAM。
我得到握手失败错误的主要原因是Arduino无法读取握手响应消息的“Sec-WebSocket-Accept”标头(也是许多其他标头),我通过调试代码确保它们被发送在服务器上。
实际上这个问题和许多其他奇怪的行为一直在发生,直到我减少程序运行期间使用的内存量。