• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

"Вешается" ESP при частых запросах...

DrJarold

Member
Уважаемые ESPшнки, прошу вашей помощи... Есть код, который предназначен для обмена данными между ESP - Arduino по UART, в принципе все работает. Однако есть одно но... Если начать "флудить" запросами на адрес по которому работает ESP, то она зависает, т.е. в браузере идет загрузка и ничего не происходит пока не перезагрузишь ESP, так как все последующий запросы уже тоже не проходят. Однако если к примеру отключить Arduino и напрямую подключить ESP к Com порту, то уже "зафлудить" ее становиться тяжелее, но возможно, однако в этом случае если остановить загрузку то следующие запросы проходят нормально... Не могу понять почему это происходит!!!
Код:
#include <ESP8266WiFi.h>

byte ERROR_CONNECTION_TO_ACCESS_POINT = -2;
byte REQUEST_ERROR = -1;
byte REQUEST_GET_DEVICE = 0;
byte REQUEST_GET_CANAL_STATE = 1;
String ESP_REQUEST = "ESP_REQUEST_";
#define TIMEOUT 500
int waitCount = TIMEOUT;
const char* ssid = "";
const char* password = "";
WiFiServer server(80);
void setup() {
  Serial.begin(9600);
  Serial.println("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  server.begin();
  Serial.println(WiFi.localIP());
  Serial.flush();
}

void loop() {
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  while (!client.available()) {
    delay(1);
  }

  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();

  // Match the request
  String val = ESP_REQUEST + REQUEST_ERROR;
  if (req.indexOf("/api/device") != -1)
    val = ESP_REQUEST + REQUEST_GET_DEVICE;
  else if (req.indexOf("/api/chanal") != -1)
    val = ESP_REQUEST + REQUEST_GET_CANAL_STATE;
  else {
    ReturnErrorResponse(client, "Error request URL");
    return;
  }

  Serial.println(val);
  Serial.flush();
  waitCount = TIMEOUT;
  while (Serial.available() <= 0) {
    waitCount--;
    if (waitCount <= 0) {

      ReturnErrorResponse(client, "Timeout");
      return;
    }
  }
  req = Serial.readStringUntil('\r\n');
  ReturnSuccessResponse(client, req);
}

void ReturnErrorResponse(WiFiClient client, String message) {
  String json = "{\"status\":\"error\",\"message\": " + message + ",\"data\":[]}";
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n " + json + "</html>\n";
  client.print(s);
  delay(1);

}

void ReturnSuccessResponse(WiFiClient client, String message) {
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n " + message + "</html>\n";
  client.print(s);
  delay(1);

}
Прошу прощения если задаю очевидные вопросы, которые уже обсуждались, не пинайте меня сильно я только учусь!!!!
 

Сергей_Ф

Moderator
Команда форума
@DrJarold в http у есп есть ошибки и такие атаки она не переваривает. По UDP такой проблемы нет, у меня переваривал более 30 сообщений в секунду и не вис.
 

DrJarold

Member
@Сергей_Ф т.е. вообще никак? По http? Мне бы просто добавить какое нибудь ограничение на запросы и не давать вешать устройство!
 

Сергей_Ф

Moderator
Команда форума
@Юрий Ботов э нет, корректно переваривать флуд и не виснуть, это явно на совести програмистов. С UDP ведь такого не случается. Я специально не тестировал, но 30-50 сообщений в сек по UDP перевариваются нормально, по http - дай Бог 0,5-1 в сек. Это явная ошибка. Естественно, речь не про ФЛУД.
 

Юрий Ботов

Moderator
Команда форума
С UDP ведь такого не случается.
Если у вас дома есть парочка компьютеров, попробуйте с одного (линкусового) на другой послать sudo ping -f адресвторого и посмотрите что будет. В винде такой пинг не будет работать.
Просто если вы подаете больше пакетов чем однопотоковая система успевает обработать за тот же период времени она ОБЯЗАТЕЛЬНО захлебнется. Выходов 2: от редких "выбросов" нагрузки спасает буферизация (но тогда нужно много памяти) или добавлять второй поток (процессор) чтобы прием и сортировка запросов и реальная обработка запросов выполнялась в разных потоках. И программист тут абсолютно не причем. Решения чисто хардверные.
 

Сергей_Ф

Moderator
Команда форума
@Юрий Ботов
попробовал на localhost и ничего криминального не обнаружил.
комп не завис, работал паралельно браузер, корректно прервалась работа по Ctrl+Break.
А ESP зависает и не отвисает после того как его перестали "бомбить" флудом.

Код:
sudo ping -f localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
^C
--- localhost ping statistics ---
142893 packets transmitted, 142893 received, 0% packet loss, time 12796ms
rtt min/avg/max/mdev = 0.008/0.009/0.439/0.005 ms, ipg/ewma 0.089/0.009 ms
Так же попробовал зафлудить свой смартфон на Андроид - результат такой же.
 

Юрий Ботов

Moderator
Команда форума
Ну с локалхостом не совсем корректно... когда начинает тормозить он и пинг генерирует медленнее, в результате все нормально. Попробую с другой стороны: вот процессор спокойно работает, а тут пришло прерывание от wifi, процессор начал отрабатывать прерывание, не успел, а тут еще одно прерывание (я немного утрирую и описываю упрощенно), переменные старого прерывания остаются в стэке, создаются переменные нового прерывания обрабатывается прерывание... опять новое прерывание, переменные второго прерывания в стэке, создаются переменные 3-го кладутся в стэк и так далее... стэк растет...растет...растет и буквально через десяток таких вложенных прерываний он вторгается в область данных и крушит там все подряд (это не интерпретатор, он выход за границы не проверяет), потом еще через пару десятков вложенных прерываний стэк начинает крушить область программы (да! программа в esp тоже в ОЗУ). После этого... можно сколько угодно выключать внешний флуд. Программы то уже НЕТ.
 

Сергей_Ф

Moderator
Команда форума
@Юрий Ботов проверил флуд пинга на ESP - пакеты теряются, но ESP не вешается. И даже спокойно отрабатывает запросы HTTP, так что думаю Вы не правы и прграмисты что то напортачили именно с HTTP.
 

Юрий Ботов

Moderator
Команда форума
Просто обработка HTTPзанимает значительно больше команд (времени) чем простой ответ на Ping. Ну как скажете...
 

nikolz

Well-known member
Да действительно UDP решает проблему, спасибо.
ESP по TCP может работать с одним открытым соединением и до 2-х еще в очереди. Эта проблема известна давно.
Поэтому давно рекомендую UDP.
Но некоторые, особо умные, все продолжают эксперименты с линуксом и дают бестолковые советы.
 
Сверху Снизу