我试图通过单个ESP32 AP配置多个连接的ESP32站。对我来说,最简单的方法是将单个广播UDP数据包发送到255.255.255.255。然而,我的站正在监听一个开放的UDP端口根本没有收到广播数据。是否需要在站点/AP上配置其他内容才能实现此功能?
我已经做了一些阅读,似乎lwip/opt.h可能已经禁止检测广播数据包,但在设置IP_SOF_BROADCAST
和IP_SOF_BROADCAST_RECV
后,我没有看到任何差异。
这是我当前的站UDP侦听任务:
static void udp_listen_task(void *pvParameters)
{
while (1) {
struct sockaddr_in dest_addr;
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(PORT);
int addr_family = AF_INET;
int ip_protocol = IPPROTO_IP;
inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1);
int sock = socket(addr_family, SOCK_DGRAM, ip_protocol);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
break;
}
//ESP_LOGI(TAG, "Socket created");
int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err < 0) {
ESP_LOGE(TAG, "Socket unable to bind: err %d", err);
}
while (1) {
struct sockaddr_in6 source_addr;
socklen_t socklen = sizeof(source_addr);
int len = recvfrom(sock, &controller_msg, sizeof(controller_msg), 0, (struct sockaddr *)&source_addr, &socklen);
//Error occurred during receiving
if (len < 0) {
ESP_LOGE(TAG, "recvfrom failed: errno %d", errno);
break;
}
// Data received
else {
// Get the sender's ip address as string
if (source_addr.sin6_family == PF_INET) {
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
} else if (source_addr.sin6_family == PF_INET6) {
inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1);
}
// Post event to act on message
xEventGroupSetBits(conn_evt, CONN_EVT_UDP_RECEIVED);
}
}
if (sock != -1) {
ESP_LOGE(TAG, "Shutting down socket and restarting...");
shutdown(sock, 0);
close(sock);
}
}
vTaskDelete(NULL);
}
看起来您的监听套接字缺少SO_BROADCAST
选项。在创建套接字之后,您需要这样做:
int bc = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &bc, sizeof(bc)) < 0) {
ESP_LOGE(TAG, "Failed to set sock options: errno %d", errno);
closesocket(sock);
break;
}
看一下这个例子
提示:如果这没有帮助,那么也许你还需要一个快速检查,以验证发送者实际上是广播。将计算机连接到相同的WiFi网络,然后运行WireShark查看空气中的UDP数据包。