• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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 "ПОМЕСТИТЬ".
 
Сверху Снизу