Продолжаем работу с протоколами модели OSI и на данном уроке мы попытаемся создать простой сервер HTTP, который позволит нам принять запрос документа от клиента, обработать его и в ответ направить клиенту нужную информацию. Также мы раньше подобные задачи решали с использованием других контроллеров, в том числе и родственного ESP8266, поэтому думаю, что с данной задачей мы без особого труда справимся. Сервер считается простым, так как отвечать он будет на запросы не любых документов, а только главной страницы и иконки приложения. Также мы для упрощения задачи не используем шифрование.
Дисплей нам на данном уроке не потребуется, поэтому схема наша будет состоять только из отладочной платы с контроллером ESP32, подключенной к USB-порту компьютера
Проект за основу мы возьмём из прошлого урока с именем WIFI_STA_TCP_SERVER и присвоим ему имя WIFI_STA_HTTP_SERVER.
Откроем проект в Espressif IDE и удалим файлы lcd2004.h, lcd2004.c, i2c_user.h и i2c_user.c, так как с дисплеем мы работать не будем. Также подключение данных модулей мы удалим и в файле CMakeLists.txt
set(COMPONENT_SRCS "main.c wifi.c tcp.c
i2c_user.c lcd2004.c")
В файле Kconfig.projbuild удалим секции, отвечающие за ножки I2C
config SDA_GPIO
int "SDA GPIO number"
range 0 48
default 21
help
GPIO number SDA.
config SCL_GPIO
int "SCL GPIO number"
range 0 48
default 22
help
GPIO number SCL.
Зайдём в конфигуратор и изменим порт на значение по умолчанию для работы с протоколом HTTP
Удалим подключение заголовочного файла из main.h и tcp.h
#include "lcd2004.h"
В функции app_main файла main.c удалим строки связанные с инициализацией дисплея
ret = i2c_ini();
ESP_LOGI(TAG, "i2c_ini: %d", ret);
LCD_ini();
Файлы tcp.h и tcp.c переименуем соответственно в http.h и http.c.
Изменим подключение модуля также в файле CMakeLists.txt
set(COMPONENT_SRCS "main.c wifi.c http.c")
Перейдём в файл http.c и удалим функцию vLCDTask вместе с телом.
Удалим также и функцию client_socket_task.
Структуры и очереди нам также не потребуются
typedef struct struct_client_socket_t {
struct sockaddr_in cliaddr;
socklen_t sockaddrsize;
int accept_sock;
uint16_t y_pos;
} struct_client_socket;
struct_client_socket client_socket01;
//-------------------------------------------------------------
typedef struct
{
unsigned char y_pos;
unsigned char x_pos;
char *str;
} qLCDData;
//------------------------------------------------
xQueueHandle lcd_string_queue = NULL, xQueueClose = NULL, xQueueCloseAsk = NULL;
Переименуем строку
static const char *TAG = "http";
Также переименуем функцию задачи
void http_task(void *pvParameters)
Не забываем также о прототипе в заголовочном файле. Также в функции app_main файла main.c переименуем аргументы в создании задачи
xTaskCreate(http_task
, «http_task«, 4096, NULL, 5, NULL);
Вернёмся в файл http.c и в функции http_task удалим объявление хендла задачи дисплея
TaskHandle_t xLCDTaskHandle = NULL;
Удалим инициализацию позиции
unsigned char y_pos = 0;
Удалим также вот эти строки
qLCDData xLCDData;
char str1[21];
xLCDData.y_pos = 1;
xLCDData.str = str1;
Удалим и вот эти строки, также связанные с дисплеем
lcd_string_queue = xQueueCreate(10, sizeof(qLCDData));
xQueueClose = xQueueCreate(10, sizeof(unsigned char));
xQueueCloseAsk = xQueueCreate(10, sizeof(unsigned char));
xTaskCreate(vLCDTask, «vLCDTask», 2048, NULL, 2, &xLCDTaskHandle);
Здесь удалим перевод строки, чтобы не создавалась лишняя, в функции для вывода логов строки переводятся автоматически
ESP_LOGI(TAG, «Create socket…\n«);
…
ESP_LOGE(TAG, «socket not created\n«);
Тут исправим грамматическую ошибочку
//Свяжем сокет с адресом сервера
В следующем условии удалим уничтожение задачи и очереди
vQueueDelete(lcd_string_queue);
vTaskDelete(NULL);
Тело следующего условия удалим полностью
if(accept_sock >= 0)
{
client_socket01.accept_sock = accept_sock;
client_socket01.cliaddr = cliaddr;
client_socket01.sockaddrsize = sockaddrsize;
client_socket01.y_pos = y_pos%4;
xTaskCreate(client_socket_task, "client_socket_task", 4096, (void*)&client_socket01, 5, NULL);
y_pos++;
}
В конце тела функции удалим вот эти строки
sprintf(str1, "Disonnected");
xQueueSendToBack(lcd_string_queue, &xLCDData, 0);
vTaskDelay(2000 / portTICK_RATE_MS);
vTaskDelete(xLCDTaskHandle);
vQueueDelete(lcd_string_queue);
Теперь у нас хотя бы будет собираться код.
Добавим переменную в объявление
int sockfd, accept_sock, ret;
Объявим указатель на буфер, а также объявим и инициализируем длину буфера
1 2 3 |
socklen_t sockaddrsize; uint8_t *buf; int buflen = 1024; |
В условии, тело которого мы удалили, запросим память для буфера и попытаемся принять от клиента пакет
1 2 3 4 |
if(accept_sock >= 0) { buf = heap_caps_malloc(1024, MALLOC_CAP_8BIT); ret = recvfrom(accept_sock, buf, buflen, 0, (struct sockaddr *)&cliaddr, &sockaddrsize); |
Теперь нам надо будет подготовить документы, которые мы будем предоставлять клиенту на его запросы.
Сделаем мы это так, как делали раньше с AVR, подготовив массив с помощью утилиты makefsdata (в конце страницы будет ссылка на архив утилиты с примерами страницы и иконки). Содержимое страницы и заголовка HTTP мы поместим в глобальные массивы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
static const char *TAG = "http"; //------------------------------------------------------------- const char http_header[] = {"HTTP/1.1 200 OK\r\nServer: nginx\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n"}; const uint8_t index_htm[] = { 0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x68,0x74,0x6d,0x6c,0x3e,0x0d, 0x0a,0x3c,0x68,0x74,0x6d,0x6c,0x20,0x6c,0x61,0x6e,0x67,0x3d,0x22,0x72,0x75,0x22, 0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x09,0x3c,0x6d,0x65,0x74, 0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x43,0x6f, 0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74, 0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20, 0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x20,0x2f, 0x3e,0x0d,0x0a,0x09,0x3c,0x74,0x69,0x74,0x6c,0x65,0x3e,0x45,0x53,0x50,0x33,0x32, 0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x65,0x61,0x64, 0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x09,0x3c,0x68,0x31,0x20, 0x73,0x74,0x79,0x6c,0x65,0x3d,0x22,0x74,0x65,0x78,0x74,0x2d,0x61,0x6c,0x69,0x67, 0x6e,0x3a,0x20,0x63,0x65,0x6e,0x74,0x65,0x72,0x3b,0x22,0x3e,0x45,0x73,0x70,0x20, 0x33,0x32,0x3c,0x62,0x72,0x3e,0x3c,0x62,0x72,0x3e,0x48,0x54,0x54,0x50,0x20,0x53, 0x65,0x72,0x76,0x65,0x72,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x3c,0x70,0x3e, 0x3c,0x73,0x70,0x61,0x6e,0x20,0x73,0x74,0x79,0x6c,0x65,0x3d,0x22,0x66,0x6f,0x6e, 0x74,0x2d,0x66,0x61,0x6d,0x69,0x6c,0x79,0x3a,0x20,0x54,0x69,0x6d,0x65,0x73,0x20, 0x4e,0x65,0x77,0x20,0x52,0x6f,0x6d,0x61,0x6e,0x2c,0x54,0x69,0x6d,0x65,0x73,0x2c, 0x73,0x65,0x72,0x69,0x66,0x3b,0x22,0x3e,0x45,0x53,0x50,0x33,0x32,0x20,0x69,0x73, 0x20,0x61,0x20,0x73,0x69,0x6e,0x67,0x6c,0x65,0x20,0x32,0x2e,0x34,0x20,0x47,0x48, 0x7a,0x20,0x57,0x69,0x2d,0x46,0x69,0x2d,0x61,0x6e,0x64,0x2d,0x42,0x6c,0x75,0x65, 0x74,0x6f,0x6f,0x74,0x68,0x20,0x63,0x6f,0x6d,0x62,0x6f,0x20,0x63,0x68,0x69,0x70, 0x20,0x64,0x65,0x73,0x69,0x67,0x6e,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x74, 0x68,0x65,0x20,0x54,0x53,0x4d,0x43,0x20,0x75,0x6c,0x74,0x72,0x61,0x2d,0x6c,0x6f, 0x77,0x2d,0x70,0x6f,0x77,0x65,0x72,0x20,0x34,0x30,0x20,0x6e,0x6d,0x0d,0x0a,0x74, 0x65,0x63,0x68,0x6e,0x6f,0x6c,0x6f,0x67,0x79,0x2e,0x3c,0x2f,0x73,0x70,0x61,0x6e, 0x3e,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d, 0x0a,0x3c,0x2f,0x68,0x74,0x6d,0x6c,0x3e}; //------------------------------------------------------------- |
С иконкой поступим немного по-другому. Мы её не будем собирать из двух массивов, а создадим для неё общий массив вместе с заголовком. Памяти лишней мы не истратим, так как иконка у нас одна. Зато передавать мы её будем сразу из исходного массива
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
0x0a,0x3c,0x2f,0x68,0x74,0x6d,0x6c,0x3e}; const uint8_t favicon_ico[] = { 0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, 0x0a, /* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) " (63 bytes) */ 0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, 0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, 0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, 0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, /* "Content-Length: 1150 " (18+ bytes) */ 0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20, 0x31,0x31,0x35,0x30,0x0d,0x0a, /* "Connection: Close " (19 bytes) */ 0x43,0x6f,0x6e,0x6e,0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x43,0x6c,0x6f,0x73, 0x65,0x0d,0x0a, /* "Content-type: image/x-icon " (30 bytes) */ 0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x69,0x6d, 0x61,0x67,0x65,0x2f,0x78,0x2d,0x69,0x63,0x6f,0x6e,0x0d,0x0a,0x0d,0x0a, /* raw file data (1150 bytes) */ 0x00,0x00,0x01,0x00,0x01,0x00,0x10,0x10,0x00,0x00,0x01,0x00,0x20,0x00,0x68,0x04, 0x00,0x00,0x16,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x20,0x00, 0x00,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf4,0xf4, 0xf4,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0xf4,0xf4,0xf4,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff, 0x0c,0xff,0x00,0xff,0x0c,0xff,0x00,0xff,0x0c,0xff,0x69,0x22,0x1a,0xff,0xf4,0xf4, 0xf4,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22, 0x1a,0xff,0x69,0x22,0x1a,0xff,0x69,0x22,0x1a,0xff,0xf4,0xf4,0xf4,0xff,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; |
Вернёмся в функцию http_task и поместим наш ответ на запрос главной страницы в буфер, соединив наши массивы заголовка и контента страницы, а перед этим отфильтровав всё ненужное
1 2 3 4 5 6 7 8 9 10 11 12 13 |
ret = recvfrom(accept_sock, buf, buflen, 0, (struct sockaddr *)&cliaddr, &sockaddrsize); if(ret > 0) { if ((ret >=5 ) && (strncmp((char*)buf, "GET /", 5) == 0)) { if ((strncmp((char const *)buf,"GET / ",6)==0)||(strncmp((char const *)buf,"GET /index.html",15)==0)) { strcpy((char*)buf,http_header); memcpy((void*)(buf + strlen(http_header)),(void*)index_htm,sizeof(index_htm)); } } } |
Отправим пакет клиенту
1 2 |
memcpy((void*)(buf + strlen(http_header)),(void*)index_htm,sizeof(index_htm)); write(accept_sock, (const unsigned char*)buf, strlen(http_header) + sizeof(index_htm)); |
А если запрос был на иконку, то передадим наш массив сразу, ничего не копируя и не соединяя
1 2 3 4 5 6 |
write(accept_sock, (const unsigned char*)buf, strlen(http_header) + sizeof(index_htm)); } else if (strncmp((char const *)buf,"GET /favicon.ico",16)==0) { write(accept_sock, favicon_ico, sizeof(favicon_ico)); } |
Выйдем из условия наличия ненулевого пакета (посчитайте закрывающие скобки) и разъединимся с клиентом, а затем освободим память, данную нам под буфер
1 2 3 4 5 6 |
write(accept_sock, favicon_ico, sizeof(favicon_ico)); } } } close(accept_sock); free(buf); |
В принципе, это весь код нашего простенького сервера HTTP. Соберём проект, прошьём контроллер и в терминале запомним сетевой адрес нашего сервера (отладочной платы)
Попытаемся в браузере запросить страницу и, если всё нормально, то мы получим и страницу и иконку
В анализаторе трафика у нас тоже всё нормально. Все ответы пришли, порты после получения документов отключились
Итак, на данном уроке нам удалось создать простейший HTTP-сервер, который может обрабатывать запрос документов от клиента и передавать ему их в форме пакета HTTP.
Всем спасибо за внимание!
Предыдущий урок Программирование МК ESP32 Следующий урок
Утилита для получения двоичного кода страниц и других файлов: makefsdata
Недорогие отладочные платы ESP32 можно купить здесь Недорогие отладочные платы ESP32
Недорогие отладочные платы ESP32/ESP32-C3/ESP32-S3 можно купить здесь Недорогие отладочные платы ESP32
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в Дзен (нажмите на картинку)
Сделайте проект пожалуйста где SD карта (с видео файлом) подключается к ESP32. А просмотреть этот файл можно было-бы на «допустим» планшетe.