• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

esp8266 ответ сервера

oneplayer

New member
Добрый день.
Есть проект на ESP-12E (NodeMcu v3) в котором ESP отправляет значение на веб сервер. После того как данные не сервере обработаются сервер выдает echo "gooddata"; или echo "baddata"; более ничего эта страничка не выдает.
Все хорошо работает но вот если смотреть через монитор порта на те данные что принимает ESP от сервера то видно что 90% данных это заголовки html что заметно сказывается на скорости ответа ESP пользователю.
HTTP/1.1 200 OK
Date: Tue, 06 Mar 2018 08:46:11 GMT
Server: Apache
X-Powered-By: PHP/5.5.38
Set-Cookie: PHPSESSID=bhbbb4hpadcpfs0vvr0h3u32n3; expires=Tue, 13-Mar-2018 08:46:11 GMT; Max-Age=604800; path=/; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 8
Connection: close
Content-Type: text/html; charset=UTF-8

gooddata
Код:
client.print( "GET /insert.php?id=");
          client.print(find);
          client.print(" HTTP/1.0\r\n");
          client.println("Host: example.org\r\n");
          client.println("Connection: keep-alive\r\n\r\n");
          client.println();

          delay (200);
Код:
if (client.connected())
          {
              String c = client.readString();
              if(c.indexOf("gooddata") >0)
              {
                      display.drawString(32,28, "Data send. Ok!");
                      refresh();
                      delay(1000);
              }else
              {
                      display.drawString(32,28, "Data send. Fault!");
                      refresh();
                      delay(1000);
              }
              Serial.print(c);//Deb
            client.stop();
          }

Подскажите как можно убрать эти заголовки которые съедают львиную долю времени?
Или как ускорить процесс обработки ответа от сервера?
Заранее спасибо.
 

Алексей.

Active member
oneplayer, В вашем примере ответа заголовков http есть с десяток, а html заголовков нет, видимо опечатка, но суть вопроса ясна.
сервер работает согласно протокола, не отвечать заголовками он не может. Вы выбрали пых-пых, часть заголовков как показывает поиск убрать можно через
header_remove

Просто удивительно, я полагал что протокол содержит две части, хэддшейк и обмен данными. При хэддшейке присутствуют http заголовки в запросах и ответах.
Подскажите пожалуйста в какой реализации протокола вебсокета отсутствуют заголовки, если можно какой rfc?
 
Последнее редактирование:

shuraf

Member
Разве заголовки не в момент установления связи? А потом "мелкие накладные расходы"?
 

nikolz

Well-known member
Если можете перейти на протокол UDP, то время передачи данных и получение подтверждения от сервера составит не более 10 мс.
 

Алексей.

Active member
Разве заголовки не в момент установления связи? А потом "мелкие накладные расходы"?
ТС спрашивал как обойтись без заголовков, Вы предложили вебсокет который, по вашему не использует заголовки, и тут же спрашиваете про момент старта, не понятно мне уж совсем стало, где-ж тот вебсокет без заголовков?

Если можете перейти на протокол UDP
пых-пых с вебсокетами вроде работает, а про udp не слыхал, видимо я отстал от жизни :)
 

shuraf

Member
ТС спрашивал как обойтись без заголовков, Вы предложили вебсокет который, по вашему не использует заголовки, и тут же спрашиваете про момент старта, не понятно мне уж совсем стало, где-ж тот вебсокет без заголовков?
Честно сказать, я с этим не разбирался, но из прочитанного считал, что вэбсокет гонит заголовки только при установке связи, а потом только голые данные.
А у ТС при каждом запросе заголовки и большие "накладные расходы".
Я не прав?
 

sharikov

Active member
Если можете перейти на протокол UDP, то время передачи данных и получение подтверждения от сервера составит не более 10 мс.
Из серии вредных советов.
UDP бессовестно дропают так что ответ сервера может составить бесконечность.
 

oneplayer

New member
Порезал заголовки через header_remove
PHP:
header_remove("Set-Cookie");
header_remove("Expires");
header_remove("Set-Cookie");
header_remove("X-Powered-By");
header_remove("Cache-Control");
header_remove("Pragma");
header('Content-Type:');
Ответ стал меньше по составу
Код:
HTTP/1.1 200 OK
Date: Wed, 07 Mar 2018 12:18:30 GMT
Server: Apache
Content-Length: 8
Connection: close

Но существенно на скорость получения ответа это не повлияло я бы сказал что вообще ничего не изменилось. Если дать запрос через браузер скрипт отрабатывает мгновенно. Но через ESP все равно долгий ответ.
Может я не верно использую чтение ответа? Из-за этого и такая задержка?
Настройки самого сервера менять не могу т.к. на нем крутятся несколько разношерстных сайтов и нельзя нарушить их работу.
Вариант с глючной ESP или плохим WiFi отпадает т.к. на этом проекте висят еще 3 W5100 они тоже так же долго получают ответ.
 

Алексей.

Active member
oneplayer, Вы шифруетесь, клиента не светите, по коду похож на WiFiClient, который наследует Stream, не напрямую а через почти абстрактный Client
вызываете String c = client.readString()
Смотрим в исходники
Код:
int Stream::timedRead() {
    int c;
    _startMillis = millis();
    do {
        c = read();
        if(c >= 0)
            return c;
        yield();
    } while(millis() - _startMillis < _timeout);
    return -1;     // -1 indicates timeout
}

String Stream::readString() {
    String ret;
    int c = timedRead();
    while(c >= 0) {
        ret += (char) c;
        c = timedRead();
    }
    return ret;
}
Базовый Stream будет вызывать в течении _timeout перегруженный клиентский read()
Код:
int WiFiClient::read()
{
    if (!available())
        return -1;

    return _client->read();
}
который возвращает очередной символ если он доступен
таким образом если при чтении ответа от сервера будут задержки, ожидаемой строки Вы можете не дождаться, в первом вызове readString получите только кусок "....good", проверка у вас не сработает, а во втором остаток "data" и опять проверка не сработает

Внимание, вопрос.
Почему для протокола http не был выбран HTTPClient?
Для чего такие сложности? Всё уже написано за нас :)
 

oneplayer

New member
Все работает отлично если работаю с локальным сервером и обращаюсь к нему по ip. Отправляя get без указания хоста и указания версии протокола т.е.
Код:
client.print( "GET /insert.php?id=");
client.print(find);
client.println();
В таком случае ответ занимает менее секунды.
Но у меня проект крутится на субдомене. И если не указывать имя хоста в запросе
Код:
client.println("Host: sub.example.com\r\n");
Все запросы уходят в сайт на домене example.com Хоть и в параметрах подключения указан именно нужный адрес
Код:
const char* ssid     = "WiFi";
const char* password = "pasw";
const char* host = "http://sub.example.com";
const int httpPort = 80;
Код:
WiFiClient client;
if (!client.connect(host, httpPort))
{
 

Алексей.

Active member
oneplayer,
Я думаю Вы немножко не представляете что делаете.
Выполняя client.connect(host, httpPort) в котором host = "http://sub.example.com" просто устанавливаете tcp соединение.
Все запросы уходят в сайт на домене example.com Хоть и в параметрах подключения указан именно нужный адрес
Именно нужный адрес, который резолвится из "http://sub.example.com", клиенту (WiFiClient client) домен вообще нужен только для того чтоб определить ip адрес, больше не для чего.
Предположим Вы зарегили домен второго уровня example.com и регистратор Вам дает возможность добавлять не ограниченное количество суб-доменов и Вы добавили суб-домен sub.example.com и указали тот же ip адрес что и для example.com
После того как клиент установил tcp соединение, он отправляет запрос в котором указан только метод и uri, даже версия http протокола не указана
Код:
client.print( "GET /insert.php?id=");
client.print(find);
client.println();
Заголовок Host не передаете, поэтому и сервер не знает что Вы хотели отправить запрос на суб-домен.
 

oneplayer

New member
Просьба поправить меня если я не прав или как то нарушаю всемирный баланс )). Из ситуации вышел так. Раз уж я парюсь над чтением заголовков, а потом над ответом. То почему бы не менять заголовок в зависимости от результата работы скрипта на веб сервере.

Код:
if (client.connected())
         {
             String c = client.readStringUntil('\r');
             Serial.print(c);//Deb
             if(c=="HTTP/1.1 200 OK")
             {
                     Serial.print("Data send. Ok!");
             }else
             {
                    Serial.print("Data send. Fault!");
             }

В рhp скрипте в ответы вставил подмену заголовка на отрицательный результат работы скрипта
PHP:
header("HTTP/1.1 201 OK");
Теперь если все Ок то сервер шлет мне "HTTP/1.1 200 OK". И если все не Ок то мне приходит "HTTP/1.1 201 OK".
Читая только первую строку до конца и сравнивая ее с ожидаемым ответом я понимаю каков результат запроса отправленного esp8266
В результате этого скорость ответа esp8266 человеку доли секунды

p/s/
Код 201 означает Created-"Создано". Запрос успешно выполнен и в результате был создан ресурс. Этот код обычно присылается в ответ на запрос PUT "ПОМЕСТИТЬ".
 
Сверху Снизу