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

жизненный цикл TCP подключения в espconn

_hg_

New member
Друзья, кто-нибудь (я уверен здесь такие есть) может объяснить, как работает ESP8266 с espconn при подключении в качестве клиента: ESP8266 (client) - TCP connection ---> SERVER (e.g. google.com) ?

То есть я хочу узнать как оно работает с данными изнутри. Почему часто из черного ящика espconn доносится "already freed" и всякие LoadProhibitedCause ?

Вот например существует функция

Код:
int work_controller (struct controller_data *ctl_data, uint32_t command)
{
    // К этому освобождению ранее выделенной структуры пришёл методом научного втыка
    // Если это не сделать, а взять и переинициализировать структуру, выделенную ранее (переданную сюда в качестве аргумента), то происходят крики изнутри соединения (аномалии всякие LoadProhibited и т.д.)
    // ВОТ В ЭТОМ И ХОЧУ РАЗОБРАТЬСЯ. ЧТО ПРОИСХОДИТ ВНУТРИ.
    // ПОЧЕМУ НЕЛЬЗЯ ПЕРЕИСПОЛЬЗОВАТЬ ОДНУ СТРУКТУРУ ?
    if (ctl_data) {
        free(ctl_data);
        ctl_data = NULL;
    }

//---------------------- cut ------------------------// отсюдя начиналась функция до научного втыка.

    if (!ctl_data) {
        ctl_data = (struct controller_data *)zalloc(sizeof(struct controller_data) + SEND_BUFFER_MAX);
        if (!ctl_data) {
            return -1;
        }
        ctl_data->data = (uint8_t *)(ctl_data + 1);
    }
    else {
        // переиспользуем ранее выделенный буфер:
        // тут я заполняю структуру и обнуляю буфер данных
        // ВНИМАНИЕ: если эту переинициализированную структуру использовать,
        // то происходит LoadProhibited где-то в попытке соединения с удаленным сервером.
        // До использования этой структуры моим кодом дело не доходит. Моя ошибка исключена.
        memset(((uint8_t *)ctl_data->data + sizeof(struct controller_data)), 0x00, SEND_BUFFER_MAX);
    }

    if (command == CONTROLLER_API_STOP) {
        if (ctl_data) free(ctl_data);
        return 0;
    }

    ctl_data->command = command;

    switch (ctl_data->command) {

    case CONTROLLER_API_SAVE_METRIC:

        if (!controller_save_metric(ctl_data)) {
            free(ctl_data);
            return -1;
        }
        break;

    case CONTROLLER_API_ADD_DEVICE:
    
        if (!controller_add_device(ctl_data)) {
            free(ctl_data);
            return -1;
        }
        break;

    default:
        free(ctl_data);
        return -1;
    }

    // эта строка для отладки и исключения ошибок в динамической передаче IP
    struct ipaddr controller_ip; ((uint32_t *)&controller_ip)[0] = (100 << 24 | 0 << 16 | 168 << 8 | 192);

    struct tcp_handlers h;
    memset(&h, 0, sizeof(struct tcp_handlers));

    h.tcp_connected        = work_connected;
    h.tcp_write_finish    = work_write_finish;
    h.tcp_received        = work_received;
    h.tcp_sent            = work_sent;
    h.tcp_reconnected    = work_reconnected;
    h.tcp_disconnected    = work_disconnected;

    // create_tcp_connection: выделяет espconn, заполняет IP, PORT, espconn->reverse = ctl_data, калбэки и таймаут.
    // а затем создает подключение. и следующая стадия - work_connected, который отправляет первую порцию данных.
    // а в work_disconnected мы меняем команду на следующую (CONTROLLER_API_ADD_DEVICE) и снова вызываем эту функцию для совершения следующего (если ещё не CONTROLLER_API_STOP) подключения.
    if (create_tcp_connection(&controller_ip, 80, &h, (void *)ctl_data, 30)) {
        free(ctl_data);
        return -1;
    }
    return 0;
}
Вот вопрос: ЧТО ПРОИСХОДИТ ВНУТРИ ? Почему нельзя ПЕРЕИСПОЛЬЗОВАТЬ ОДНУ СТРУКТУРУ ?
Не могу найти описания жизненного цикла этих espconn. Их не существует или мне нужно повысить уровень гугления ?
 
Последнее редактирование:

pvvx

Активный участник сообщества
Их не существует или мне нужно повысить уровень гугления ?
"Их не существует", "повысить уровень гугления" до:
[inline]err_t tcp_write(struct tcp_pcb * pcb, void * dataptr, u16_t len, u8_t apiflags)[/inline]
рассмотреть значения и почему существует apiflags.

Так-же "повысить уровень гугления" до: как распределяется HEAP. При образовании новой структуры psb, Lwip выделяет в памяти место под неё и возвращает вам ID, который является адресом-указателем на эту структуру. При закрытии соединения, LwIP освобождает эту память. Далее, к примеру, инициализирует другую pcb для другого соединения. При запросе у менеджера Heap места под новую структуру он, с вероятностью в 90%, получит тот –же адрес, следовательно такую-же ID pcb. Если вы не перехватываете все калбаки от LwIP, то ваши процедуры далее будут работать с чужой pcb :)

Espconn по тому никем и не пользуется, что там куча ошибок…
Единственная цель espconn – избавить пользователя SDK от сопряжения с LwIP TLS/SSL соединений. Но, т.к. на сегодня ESP8266 не в состоянии обеспечивать современный уровень TLS/SSL соединений с любым общественным сервером в инет, то espconn является никчемной примочкой, пожирающей память и вносящей ошибки в ПО.
 
Последнее редактирование:
  • Like
Реакции: _hg_
Сверху Снизу