Arduino 不支持使用 websocket 协议的大于 65535 个字符的消息?

Arduino does not support messages larger than 65535 characters using websocket protocol?

我正在使用以下 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, I couldn't find other libraries that support WiFi shield since most of the webscket libraries are written for 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 shield 上的 websocket?

任何解决方案或想法将不胜感激。

提前致谢。

如果不查看库的代码,更改最大帧长度可能不安全,因为 websocket protocol 根据有效载荷的长度对有效载荷长度进行不同的编码:

Payload length: 7 bits, 7+16 bits, or 7+64 bits.

The length of the "Payload data", in bytes: if 0-125, that is the payload length. If 126, the following 2 bytes interpreted as a 16-bit unsigned integer are the payload length. If 127, the following 8 bytes interpreted as a 64-bit unsigned integer (the most significant bit MUST be 0) are the payload length.

当库说它不支持超过 65535 字节的有效负载长度时,这可能意味着它没有实现 64 位长度编码。

经过多次试验,程序的行为非常奇怪,这让我抓狂,我发现问题是我在我的程序中使用了太多的字符串,这使得 Arduino-Uno 很容易 运行 内存不足。

我收到握手失败错误的主要原因是 Arduino 无法读取我制作的握手响应消息的 "Sec-WebSocket-Accept" header(还有许多其他 header)通过在服务器上调试代码确保它们已发送。

实际上这个问题和许多其他奇怪的行为一直在发生,直到我减少了程序 运行 期间使用的内存量。