javascript - 如何防止 Ajax 溢出/服务器崩溃? (Arduino/ESP8266环境)

标签 javascript css ajax arduino esp8266

我最近一直在学习如何在 Arduino 中编程以在 Adafruit HUZZAH ESP8266 breakout 上托管 HTML/CSS/Javascript 网页,所以如果我的方法完全错误,请原谅我。

我正在使用 Ajax 更新页面上的一些压力表值,它工作了一段时间,但最终我得到了 ERR_CONNECTION_TIMED_OUT

我一直都遇到这个问题,尤其是在我刚刚启动服务器时。如果我最终重置 wifi 卡足够多次,它似乎加载得很好但是 这是有问题的,而且非常不稳定。

我还注意到,似乎 ESP8266 一次只能处理一个用户,一旦我尝试从另一台计算机/手机连接,服务器就会崩溃,我必须按下重置按钮才能获得它在那个新主机上工作。

有人可以帮助我了解我是否只是以非常低效的方式使用 Ajax 或者为什么会发生这种情况?

(删除旧代码以适应新代码)

编辑: 所以我相信我已经通过两种方式改进了我的代码:

  • 我已经修改了数百个 client.println() 语句,而是将 html/css/js 内容存储到四个单独的字符数组中,然后仅在四个 client.println() 语句中打印出来。

  • 我还通过在逗号分隔内一次发送所有变量,将我的 ajax 调用次数从 5 个(不包括仍然需要的与 LED 灯对应的两个)减少到 1 个然后我将相应的变量内容单独过滤掉的字符串。

但是,我仍然遇到频繁但随机的 ERR_CONNECTION_TIMED_OUT 错误,我说随机是因为我最近能够通过连续成功的 ajax 调用成功运行服务器近两个小时,然后错误消息开始出现,然后紧接着重新启动服务器仅 30 秒内就会出现更多错误消息。

此时我无法确定我是否仍在低效地使用 ajax,或者这是否仅仅是由于 ESP8266 的限制?

#include <ESP8266WiFi.h>
#include <WiFiClient.h> 
#include <Wire.h>

WiFiServer server(80);
WiFiClient client;
String HTTP_req;
String req;
double test = 42;
String LEDstatus = "off"; 

(Some variable initializations removed for space)

char webpagePartOne[2500]; 
char webpagePartTwo[2500];  
char webpagePartThree[2500];  
char webpagePartFour[2500];


void switchLEDon() {

//Serial.println("TEST LED ON");

int ledStatusLength = 1;

subsys = 0x13; 

//Account for the end of message
messageLength = ledStatusLength + 2;

messageContent = 1;

Serial.write(som);
Serial.write(messageLength);
Serial.write(subsys);
Serial.write(messageContent);
Serial.write(eom);
//Serial.println("");
//Serial.println("TURN LED ON|");
LEDstatus = "on";
} //end switchLEDon

void switchLEDoff() {
     (almost the same as switchLEDon(), removed to lower char count here)
} //end switchLEDoff

void setStatus(WiFiClient cl) {

currFluid += 22;

if(currFluid > 100)
{
    currFluid -= 100;
}

cl.print(currNumRefresh);
cl.print(",");
cl.print(currPressureC);
cl.print(",");
cl.print(currPressureD);
cl.print(",");
cl.print(currPressureE);
cl.print(",");
cl.print(currFluid);
}

void setup() {
  Serial.begin(115200);

  pinMode(LED_PIN, OUTPUT);
WiFi.begin(SSID, pass); 
while (WiFi.status() != WL_CONNECTED) 
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");

// Start the server
server.begin();
Serial.println("Server started");

Serial.println(WiFi.localIP());
}

void loop() {


//Communication Protocol
if(Serial.available() > 0)
{
    //Serial.print("SERIAL.AVAILABLE: ");
    //Serial.println(Serial.available());

    //delay(1000);

    if(initialCounter == 0)
    {
        rx_byte = Serial.read();
    /*
        //Print Start of Message
        Serial.print("0x");
        if(rx_byte<0x10)
        {
            Serial.print("0");
        }
        Serial.println(rx_byte, HEX);
    */
        //Serial.println(rx_byte, BIN);
        //Serial.println(rx_byte);

        initialCounter++;
    }


    if((!messageBegun) && (rx_byte == som))
    {
        messageBegun = true;

        //Serial.println("MESSAGE BEGUN TRUE");
    } //end if (messageInProgress && rx_byte)

    if((messageBegun) && (!messageInProgress))
    {
        serialCurrent = Serial.available();

        if(serialCurrent > 0)
        {      
            receivedMessageLength = (uint8_t)Serial.read();
        /*
            Serial.print("MESSAGE LENGTH: ");
            Serial.println(receivedMessageLength);
        */
            messageBegun = false;

            messageInProgress = true;

            //Serial.println("MESSAGE IN PROGRESS TRUE");

        } //end if (serialCurrent)
    } //end if (messageBegun && messageInProgress)

    if(messageInProgress)
    {
        serialCurrent = Serial.available(); 

        if(serialCurrent >= receivedMessageLength)
        {

            Serial.readBytes(rxBuff, receivedMessageLength);

            if((byte)rxBuff[receivedMessageLength-1] != eom)
            {
                //Serial.println("ERROR");
                //Serial.write(Serial.read());
            } //end if (rxBuff != eom)

            else
            {
                messageInProgress = false; 

                for(int i=0; i<receivedMessageLength; i++)
                {
                    if(rxBuff[i] == eom)
                    {
                    /*
                        //Print End of Message
                        Serial.print("0x");
                        if(rx_byte<0x10)
                        {
                            Serial.print("0");
                        }
                        Serial.println(rxBuff[i], HEX);
                    */
                        initialCounter = 0;

                        receivedMessageLength = 0;

                    } //end if

                    else if(i == 0)
                    {
                        receivedSubsys = rxBuff[i]; 
                    /*
                        //Print Subsystem
                        Serial.print("0x");
                        if(rx_byte<0x10)
                        {
                            Serial.print("0");
                        }
                        Serial.println(rxBuff[i], HEX);
                    */
                    } //end if
                    else
                    {
                        if(receivedSubsys == 0x14)
                        {
                            currNumRefresh = rxBuff[i];
                        } //end if

                        else if(receivedSubsys == 0x15)
                        {
                            currPressureC = rxBuff[i];
                        } //end else if

                        else if(receivedSubsys == 0x16)
                        {
                            currPressureD = rxBuff[i];
                        } //end else if

                        else if(receivedSubsys == 0x17)
                        {
                            currPressureE = rxBuff[i];
                        } //end else if

                    } //end else
                } //end for

            } //end else

        } //end if (serialCurrent)

    } //end if (messageInProgress)
} //end if (Serial.available)

WiFiClient client = server.available();
if (client) { 
    boolean currentLineIsBlank = true;
    String currentLine = "";
    /*
    if(digitalRead(LED_PIN))
    {
        LEDstatus = "on";
    }
    else if(!digitalRead(LED_PIN))
    {
        LEDstatus = "off";
    }
    */
    while (client.connected()) {
        if (client.available()) { 
            char c = client.read();
            HTTP_req += c;

            if (c == '\n' && currentLineIsBlank) 
            {
                client.println("HTTP/1.1 200 OK");
                client.println("Content-Type: text/html");
                client.println("Connection: keep-alive");
                client.println();

                //LED Functions
                if (HTTP_req.indexOf("ajax_LED_switch_on") > -1) {
                    switchLEDon();
                }
                else if(HTTP_req.indexOf("ajax_LED_switch_off") > -1) {
                    switchLEDoff();
                }
                else if(HTTP_req.indexOf("ajax_set_status") > -1) {
                    setStatus(client);
                } 
                else {

                //Part One

                    strcpy(webpagePartOne,"<!DOCTYPE html>\n"); 
                    strcat(webpagePartOne,"<html>\n");
                        strcat(webpagePartOne,"<head>\n");
                        strcat(webpagePartOne,"<title>Adafruit HUZZAH ESP8266</title>\n");
                        strcat(webpagePartOne,"<style type='text/css'>\n");

                            (css here removed for space)

                        //Part Two

                            (Some more css here removed for space)

                        strcat(webpagePartTwo,"</style>\n");
                        strcat(webpagePartTwo,"<script>\n");

                            strcat(webpagePartTwo,"var currPressureTest = 0;\n");
                            strcat(webpagePartTwo,"var currFluidTest = 0;\n");

                            //Set Status function
                            strcat(webpagePartTwo,"function setStatus(){\n");

                                strcat(webpagePartTwo,"nocache = \"&nocache=\"+ Math.random() * 1000000;\n");
                                strcat(webpagePartTwo,"var request = new XMLHttpRequest();\n");
                                strcat(webpagePartTwo,"request.onreadystatechange = function() {\n");
                                    strcat(webpagePartTwo,"if (this.readyState == 4) {\n");
                                        strcat(webpagePartTwo,"if (this.status == 200) {\n");
                                            strcat(webpagePartTwo,"if (this.responseText != null) {\n");

                                                strcat(webpagePartTwo,"var totalStatus = this.responseText;\n");

                                                strcat(webpagePartTwo,"var splitStatus = totalStatus.split(',');\n");

                                                //strcat(webpagePartThree,"alert('Pressure C: ' + splitStatus[0] + ', Pressure D: ' + splitStatus[1] + ', Pressure E: ' + splitStatus[2]);\n");

                                                //Num Refresh
                                                strcat(webpagePartTwo,"document.getElementById(\"demo\").innerHTML = splitStatus[0];\n");

                                                //PRESSURE C
                                                strcat(webpagePartTwo,"var pressureValue = document.querySelector('.gauge-c');\n");
                                                strcat(webpagePartTwo,"pressureValue.style.transform = 'rotate('+ splitStatus[1] +'deg)';\n");

                                                strcat(webpagePartTwo,"var pressureText = (((splitStatus[1])/180)*100).toFixed(0);\n");
                                                strcat(webpagePartTwo,"document.getElementById(\"pressurePercentC\").innerHTML = pressureText + '%';\n");

                                                strcat(webpagePartTwo,"if(pressureText > 75){\n");
                                                    strcat(webpagePartTwo,"pressureValue.style.background = 'red';\n");   
                                                strcat(webpagePartTwo,"}\n");

                                                strcat(webpagePartTwo,"else if(pressureText > 25 && pressureText < 75){\n");
                                                    strcat(webpagePartTwo,"pressureValue.style.background = 'yellow';\n"); 
                                                strcat(webpagePartTwo,"}\n");

                                                strcat(webpagePartTwo,"else if(pressureText < 25){\n");
                                                    strcat(webpagePartTwo,"pressureValue.style.background = 'green';\n");
                                                strcat(webpagePartTwo,"}\n");                            

                                                //PRESSURE D
                                                strcat(webpagePartTwo,"var pressureValue = document.querySelector('.gauge-d');\n");
                                                strcat(webpagePartTwo,"pressureValue.style.transform = 'rotate('+ splitStatus[2] +'deg)';\n");

                                                strcat(webpagePartTwo,"var pressureText = (((splitStatus[2])/180)*100).toFixed(0);\n");
                                                strcat(webpagePartTwo,"document.getElementById(\"pressurePercentD\").innerHTML = pressureText + '%';\n");

                                                strcat(webpagePartTwo,"if(pressureText > 75){\n");
                                                    strcat(webpagePartTwo,"pressureValue.style.background = 'red';\n");   
                                                strcat(webpagePartTwo,"}\n");

                                                strcat(webpagePartTwo,"else if(pressureText > 25 && pressureText < 75){\n");
                                                    strcat(webpagePartTwo,"pressureValue.style.background = 'yellow';\n"); 
                                                strcat(webpagePartTwo,"}\n");

                                                strcat(webpagePartTwo,"else if(pressureText < 25){\n");
                                                    strcat(webpagePartTwo,"pressureValue.style.background = 'green';\n");
                                                strcat(webpagePartTwo,"}\n");


                                                //PRESSURE E
                                                strcat(webpagePartTwo,"var pressureValue = document.querySelector('.gauge-e');\n");
                                                strcat(webpagePartTwo,"pressureValue.style.transform = 'rotate('+ splitStatus[3] +'deg)';\n");

                                                strcat(webpagePartTwo,"var pressureText = (((splitStatus[3])/180)*100).toFixed(0);\n");
                                                strcat(webpagePartTwo,"document.getElementById(\"pressurePercentE\").innerHTML = pressureText + '%';\n");

                                            //Part Three

                                                strcpy(webpagePartThree,"if(pressureText > 75){\n");
                                                    strcat(webpagePartThree,"pressureValue.style.background = 'red';\n");   
                                                strcat(webpagePartThree,"}\n");

                                                strcat(webpagePartThree,"else if(pressureText > 25 && pressureText < 75){\n");
                                                    strcat(webpagePartThree,"pressureValue.style.background = 'yellow';\n"); 
                                                strcat(webpagePartThree,"}\n");

                                                strcat(webpagePartThree,"else if(pressureText < 25){\n");
                                                    strcat(webpagePartThree,"pressureValue.style.background = 'green';\n");
                                                strcat(webpagePartThree,"}\n");


                                                //FLUID LEVEL
                                                strcat(webpagePartThree,"var fluidValue = document.querySelector('.fluidMeter');\n");
                                                strcat(webpagePartThree,"fluidValue.value = splitStatus[4];\n");

                                                strcat(webpagePartThree,"var fluidText = splitStatus[4];\n");
                                                strcat(webpagePartThree,"document.getElementById(\"fluidPercent\").innerHTML = fluidText + '%';\n");

                                strcat(webpagePartThree,"}}}}\n");
                                strcat(webpagePartThree,"request.open(\"GET\", \"ajax_set_status\" + nocache, true);\n");
                                strcat(webpagePartThree,"request.send(null);\n");

                                strcat(webpagePartThree,"setTimeout('setStatus()', 5000);\n");

                            strcat(webpagePartThree,"}\n");

                            strcat(webpagePartThree,"function LEDswitch(){\n");
                                strcat(webpagePartThree,"var LEDswitchCheck = document.getElementById('myonoffswitch').checked;\n");

                                strcat(webpagePartThree,"if(LEDswitchCheck){\n");
                                    strcat(webpagePartThree,"nocache = \"&nocache=\"+ Math.random() * 1000000;\n");
                                    strcat(webpagePartThree,"var request = new XMLHttpRequest();\n");
                                    strcat(webpagePartThree,"request.onreadystatechange = function() {\n");
                                        strcat(webpagePartThree,"if (this.readyState == 4) {\n");
                                            strcat(webpagePartThree,"if (this.status == 200) {\n");
                                                strcat(webpagePartThree,"if (this.responseText != null) {\n");
                                                    //strcat(webpagePartThree,"document.getElementById(\"LEDbtn\").innerHTML = this.responseText;\n");
                                    strcat(webpagePartThree,"}}}}\n");
                                    strcat(webpagePartThree,"request.open(\"GET\", \"ajax_LED_switch_on\" + nocache, true);\n");
                                    strcat(webpagePartThree,"request.send(null);\n");
                                strcat(webpagePartThree,"}\n");
                                strcat(webpagePartThree,"else if(!LEDswitchCheck) {\n");
                                    strcat(webpagePartThree,"nocache = \"&nocache=\"+ Math.random() * 1000000;\n");
                                    strcat(webpagePartThree,"var request = new XMLHttpRequest();\n");
                                    strcat(webpagePartThree,"request.onreadystatechange = function() {\n");
                                        strcat(webpagePartThree,"if (this.readyState == 4) {\n");
                                            strcat(webpagePartThree,"if (this.status == 200) {\n");
                                                strcat(webpagePartThree,"if (this.responseText != null) {\n");
                                                    //strcat(webpagePartThree,"document.getElementById(\"LEDbtn\").innerHTML = this.responseText;\n");
                                    strcat(webpagePartThree,"}}}}\n");
                                    strcat(webpagePartThree,"request.open(\"GET\", \"ajax_LED_switch_off\" + nocache, true);\n");
                                    strcat(webpagePartThree,"request.send(null);\n");
                                strcat(webpagePartThree,"}\n");
                            strcat(webpagePartThree,"}\n");
                        strcat(webpagePartThree,"</script>\n");

                    strcat(webpagePartThree,"</head>\n");
                    strcat(webpagePartThree,"<body style='background-color:#558C89;' onload=\"setStatus();\">\n"); 
                        strcat(webpagePartThree,"<div style='background-color:#74AFAD;'>\n");
                            strcat(webpagePartThree,"<h1 style='text-decoration: underline;'>Adafruit HUZZAH ESP8266</h1>\n");
                        strcat(webpagePartThree,"</div>\n");
                        strcat(webpagePartThree,"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n</div>\n<div style=\"clear:both;\"></div><p>\n");                       strcat(webpagePartThree,"<div style='background-color:#74AFAD;'>\n");
                            strcat(webpagePartThree,"<h2 style='color: red;'>LED Controls</h2>\n");

                            strcat(webpagePartThree,"<div id='LEDbtn' class='onoffswitch'>\n");

                                /*
                                if (LEDstatus == "on") 
                                {
                                    strcat(webpagePartThree,"<input type='checkbox' name='onoffswitch' class='onoffswitch-checkbox' id='myonoffswitch' checked='checked' onclick='LEDswitch()'>\n");

                                } //end if
                                */
                                /*
                                else if(LEDstatus == "off")
                                {*/
                                    strcat(webpagePartThree,"<input type='checkbox' name='onoffswitch' class='onoffswitch-checkbox' id='myonoffswitch' onclick='LEDswitch()'>\n");
                                //} //end else

                                strcat(webpagePartThree,"<label class='onoffswitch-label' for='myonoffswitch'>\n");
                                    strcat(webpagePartThree,"<span class='onoffswitch-inner'></span>\n");
                                    strcat(webpagePartThree,"<span class='onoffswitch-switch'></span>\n");
                                strcat(webpagePartThree,"</label>\n");
                            strcat(webpagePartThree,"</div>\n");
                        strcat(webpagePartThree,"</div>\n");

                        //Part Four

                        strcpy(webpagePartFour,"<div style='background-color:#74AFAD;'>\n");
                            strcat(webpagePartFour,"<h2 style='color: green;'>Num Refresh Test</h2>\n");
                            strcat(webpagePartFour,"<div id=\"demo\"><h2>Let AJAX change this text</h2></div>\n");
                        strcat(webpagePartFour,"</div>\n");
                    strcat(webpagePartFour,"</div>\n");
                    //strcat(webpagePartFour,"<div id='gaugeCounter'></div>\n");
                    strcat(webpagePartFour,"<div class='pressureRow'>\n");
                        strcat(webpagePartFour,"<div class='pressureContainer'>\n");
                            strcat(webpagePartFour,"<div class='gauge-a'></div>\n");
                            strcat(webpagePartFour,"<div class='gauge-b'></div>\n");
                            strcat(webpagePartFour,"<div class='gauge-c'></div>\n");
                            strcat(webpagePartFour,"<div class='gauge-data'><h1 id='pressurePercentC'>0%</h1></div>\n");
                        strcat(webpagePartFour,"</div>\n");
                        strcat(webpagePartFour,"<div class='pressureContainer'>\n");
                            strcat(webpagePartFour,"<div class='gauge-a'></div>\n");
                            strcat(webpagePartFour,"<div class='gauge-b'></div>\n");
                            strcat(webpagePartFour,"<div class='gauge-d'></div>\n");
                            strcat(webpagePartFour,"<div class='gauge-data'><h1 id='pressurePercentD'>0%</h1></div>\n");
                        strcat(webpagePartFour,"</div>\n");
                        strcat(webpagePartFour,"<div class='pressureContainer'>\n");
                            strcat(webpagePartFour,"<div class='gauge-a'></div>\n");
                            strcat(webpagePartFour,"<div class='gauge-b'></div>\n");
                            strcat(webpagePartFour,"<div class='gauge-e'></div>\n");
                            strcat(webpagePartFour,"<div class='gauge-data'><h1 id='pressurePercentE'>0%</h1></div>\n");
                        strcat(webpagePartFour,"</div>\n");
                    strcat(webpagePartFour,"</div>\n");

                    strcat(webpagePartFour,"<div class='fluidContainer'>\n");
                        strcat(webpagePartFour,"<meter class='fluidMeter' max='100' value='50' low='25' high='75' optimum='100'></meter>\n"); 
                        strcat(webpagePartFour,"<div class='fluid-data'><h1 id='fluidPercent'>0%</h1></div>\n");
                    strcat(webpagePartFour,"</div>\n");
                    strcat(webpagePartFour,"</body>\n");
                    strcat(webpagePartFour,"</html>");

                    client.print(webpagePartOne);
                    client.print(webpagePartTwo);
                    client.print(webpagePartThree);
                    client.print(webpagePartFour);
                }

            req = HTTP_req;    

            //    Serial.print(HTTP_req);
                HTTP_req = "";
                break;
            } //end if



        }
    }
    delay(100);
    client.stop();
}
}

最佳答案

I've also noticed that it seems that the ESP8266 can only handle one user on it at a time

我建议这样做是为了尽量不要使用可能会导致问题的 Keep-Alive header 。

client.println("Connection: keep-alive");

当您设置 Keep-alive 时,它会一直保持连接打开,这可能会导致错误。

例如,如果您的服务器有 session 超时,这应该使 session 始终保持事件状态。

keep alive也有超时和最大请求​​数

由于您每隔一段时间就会收到此错误,我认为这是您的超时 + 服务器允许在保持事件连接上接受的最大请求的问题。

删除并在没有它的情况下进行测试。

关于javascript - 如何防止 Ajax 溢出/服务器崩溃? (Arduino/ESP8266环境),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36803791/

相关文章:

javascript - catch block 中的 resolve 未定义

javascript - 从不同地方取消setInterval(NodeJS变量范围)

javascript - 在 DOM 加载后执行 append 的 &lt;script&gt; 标签

ajax - 如何描述 Web 服务器和 Web 客户端之间的交互?

javascript - 自动完成不显示字符串数组

javascript - 在javascript中反转无符号的任意二进制位

css - Normalize.css 和 Reset CSS 有什么区别?

javascript - jQuery悬停函数不透明动画

java - 通过传递输入文本框中的参数,通过 jQuery AJAX 调用 Java EE REST 服务

jquery - 使用 jquery addclass 将 css 添加到表中