Использование WiFiServer в режиме блокировки
Я изучаю сетевое программирование для ESP32 и начал с написания простого Telnet-сервера. Он использует объект WiFiServer для прослушивания порта 23 и просто записывает всё, что получает, в последовательный монитор.
Пример кода выглядит примерно так:
// Прослушивание порта 23
WiFiServer server(23);
server.begin();
// Цикл для обработки соединений
while (true) {
// Ожидание соединения
WiFiClient client = server.available();
if (client) {
...
Это работает нормально, но вызов server.available() неблокирующий, поэтому цикл выполняется непрерывно и использует 100% ресурсов процессора. На ПК я бы использовал сокет в блокирующем режиме, чтобы вызов accept() приостанавливал поток до тех пор, пока данные не станут доступны. Я делаю это, потому что 100% ресурсов процессора в многозадачной ОС — это довольно неэтично.
Мой вопрос: можно ли заставить функцию Server.available() вести себя подобно функции сокетов accept() и блокировать её до тех пор, пока соединение не станет доступным? Если нет, то что считается лучшим решением? Просто дать процессору работать на 100% или есть более эффективный способ написать код? Может быть, просто использовать тот же API сокетов BSD, что и в Linux?
@John Rennie, 👍1
Обсуждение1 ответ
Похоже, нет способа сделать блок функции WiFiServer available() доступным до получения соединения. Если проблема связана с загрузкой процессора, решением, похоже, может быть небольшая задержка после вызова функции, как предложил Юрай в комментарии.
Если кому-то интересно, API сокетов работает отлично. Я составил код ниже для быстрого теста, и он работает как надо. Если подключиться к ESP32 через Telnet, выводится сообщение, а затем соединение закрывается:
#include <lwip/sockets.h>
#include "WiFi.h"
void ConnectWiFi() {
WiFi.begin("my_ssid", "my_password", 6);
int loopcnt = 0;
while (WiFi.status() != WL_CONNECTED) {
Serial.printf("Connecting: time %d, WiFi status = %d, signal = %d\n", loopcnt++, WiFi.status(), WiFi.RSSI());
delay(1000);
}
Serial.printf("Connected: %s\n", WiFi.localIP().toString().c_str());
}
void setup() {
Serial.begin(115200);
ConnectWiFi();
}
void loop() {
// Создать, привязать и прослушивать порт 23
int sock_srv = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr addr_in;
memset(&addr_in, 0, sizeof(addr_in));
struct sockaddr_in* p_addr_in = (struct sockaddr_in*) &addr_in;
p_addr_in->sin_family = PF_INET;
p_addr_in->sin_port = htons(23);
p_addr_in->sin_addr.s_addr = INADDR_ANY;
bind(sock_srv, &addr_in, sizeof(addr_in));
listen(sock_srv, 1);
// Цикл для обработки соединений
while (true) {
// Ожидание соединения
sockaddr addr_client;
memset(&addr_client, 0, sizeof(addr_client));
int sock_client = accept(sock_srv, &addr_client, NULL);
Serial.println("Accepted connection");
// Просто завершаем сообщение и закрываем сокет
String s = "Welcome and goodbye!\r\n";
send(sock_client, s.c_str(), s.length(), 0);
closesocket(sock_client);
}
}
Привет, добро пожаловать на Arduino:SE. Не уверен, было ли это ответом на ваш вопрос или дополнительной информацией (которую, вероятно, стоит добавить в ваш вопрос, а не публиковать как ответ)., @sempaiscuba
@sempaiscuba, верное замечание: это альтернативный подход, а не ответ на вопрос, можно ли заставить WiFiServer работать в режиме блокировки. Удалю, пока не получу ответ., @John Rennie
- Как настроить пул DHCP для ESP-WIFI-MESH?
- Использование AysncUDPMessage для ESP32 для отправки строковых данных
- esp32 - кулачок застрял в повторном башмаке
- Чтение текста построчно с SD
- Arduino создает массив Json с двойными значениями и 2 десятичными знаками
- Как получить ответ HTTP_POST?
- Можно ли получить IP-адрес клиента из библиотеки Arduino Ethernet2 для W5500 во время вызова client.connected()?
- Ошибка при компиляции программы для esp32 с Preferences.h
просто позвольте потоку Arduino работать так, как это запланировано RTOS, @Juraj
@Juraj Я создаю задачи (используя vTaskCreate()) для передачи клиенту, как в подходе _accept then for k_ в Linux. Если я позволю основному потоку работать, не затормозит ли это выполнение других задач процессора?, @John Rennie
Добавьте небольшую задержку, если хотите. WiFiServer и WiFiClient реализованы через API сокетов Berkley/POSIX IDF/LwIP. Возможно, вы захотите использовать его напрямую., @Juraj
@Juraj Спасибо :-), @John Rennie