繁体   English   中英

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

[英]How to prevent Ajax overflow/server crash? (Arduino/ESP8266 Environment)

我最近学习如何在Arduino中编程以在Adafruit HUZZAH ESP8266突破上主持HTML / CSS / Javascript网页,所以如果我的方法完全关闭,请原谅我。

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

我总是得到这个,特别是当我刚启动服务器的时候。 如果我重置wifi卡足够的次数最终似乎加载很好,但它是有问题的,真的不稳定。

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

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

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

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

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

  • 我还通过在逗号分隔的字符串中一次性发送所有变量,然后我将过滤后的所有变量从五个(不计算对应于仍然需要的LED灯)的ajax调用数减少到一个相应的变量内容单独出来。

但是,我仍然遇到频繁但随机的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();
}
}

我也注意到ESP8266似乎一次只能处理一个用户

我建议尝试不要使用可能导致问题的Keep-Alive标头。

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

当您设置Keep-alive保持连接始终打开,这可能会导致错误。

例如,如果您的服务器具有会话超时,则应始终保持会话处于活动状态。

保持活动还有超时和最大请求

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

没有它,删除并测试它。

尝试使用数据包嗅探器Wireshark并截取结果

来自: https//mcuoneclipse.com/2014/11/30/tutorial-web-server-with-the-esp8266-wifi-module/

发送repsonse后尝试关闭连接:

关闭连接:CIPCLOSE

事情正在发挥作用:-)。 诀窍是我必须在发送数据后关闭连接。 我可以使用CIPCLOSE命令:

AT + CIPCLOSE =可用于关闭频道。 所以我关闭了连接

AT + CIPCLOSE = 0

因此经过大量测试后,我得出的结论是ESP8266无法处理常量的ajax更新,最终使用websockets来完成我的任务(到目前为止,它似乎比ajax更稳定)。

以下是我的结果示例: https//gist.github.com/bbx10/667e3d4f5f2c0831d00b

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM