ESP32-S3作为STA无法同时UDP广播发送和接收

birdlf
Posts: 6
Joined: Mon Nov 21, 2022 7:00 am

ESP32-S3作为STA无法同时UDP广播发送和接收

Postby birdlf » Mon Nov 28, 2022 1:21 am

请教各位大佬,我的项目是100多台分布设备,都采用ESP32-S3作为STA,然后他们之间通过UDP广播来无线通讯。
但是我参照《ESP32-C3物联网工程开发实战》里面的“broadcast_discovery”项目例程来改造的程序,接收和发送都保持同一个端口。却总是发送和接收不能同时存在。一旦先发送了,就再也接收不到广播了。而相反,如果先接收了数据,就不能再发送了。
请教各位,我应该怎么做,才能做到同时收发UDP广播呀?有什么方法能类似以前用AT指令的时候那样,设置多链接,然后用两个链接分别配置接收和发送呀?(AT+CIPSTART=0,"UDP","192.168.6.111",6000,3333 AT+CIPSTART=1,"UDP","255.255.255.255",3333,6000)
谢谢大家!
代码如下:
static esp_err_t esp_send_broadcast( uint8_t *sendBuf, uint8_t len )
{
int opt_val = 1;
esp_err_t err = ESP_FAIL;
struct sockaddr_in from_addr = {0};
socklen_t from_addr_len = sizeof(struct sockaddr_in);
char udp_recv_buf[64 + 1] = {0};

// 创建 IPv4 UDP 套接字
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
return err;
}

// 设置 SO_BROADCAST 套接字选项, 使能该套接字支持广播发送
int ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt_val, sizeof(int));
if (ret < 0) {
goto exit;
}

// 设置广播目的地址和端口
struct sockaddr_in dest_addr = {
.sin_family = AF_INET,
.sin_port = htons(3333),
.sin_addr.s_addr = htonl(INADDR_BROADCAST),
};

// 调用 sendto 接口发送广播数据
ret = sendto(sockfd, sendBuf, len, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));

exit:
close(sockfd);
return err;
}

void app_main(void)
{
uartInit();

esp_err_t err = ESP_FAIL;
struct sockaddr_in from_addr = {0};
socklen_t from_addr_len = sizeof(struct sockaddr_in);
uint8_t udp_server_buf[64 + 1] = {0};
char *udp_server_send_buf = "ESP32-C3 Smart Light https 443";

int sockfd = 0;//IPv4 UDP 套接字
int ret = 0;
// 设置广播目的地址和端口
struct sockaddr_in server_addr = {
.sin_family = AF_INET,
.sin_port = htons(6000),
.sin_addr.s_addr = htonl(INADDR_ANY),
};

while(1)
{
// 调用 recvfrom 接口接收广播数据
ret = recvfrom(sockfd, udp_server_buf, sizeof(udp_server_buf) - 1, 0, (struct sockaddr *)&from_addr, (socklen_t *)&from_addr_len);
if (ret > 0)
{
uartSend(udp_server_buf, ret);
}

int res = uartReadData();
if(res == 1)//连接WIFI
{
//Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);

ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
int a = wifi_init_sta();
if(a == 1)
{
uint8_t buf[3] = {01,02,03};
uartSend(buf, sizeof(buf));
//ret = esp_send_broadcast_Init();
}
else
{
uint8_t buf[3] = {01,03,04};
uartSend(buf, sizeof(buf));
}
}
else if(res == 2)//建立UDP服务
{
//uint8_t buf[3] = {03,03,06};
//uartSend(buf, sizeof(buf));
// 创建 IPv4 UDP 套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
uartSendData("socket error!");
}

ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0) {
uartSendData("bind error!");
close(sockfd);
}
}
else if(res == 5)//配置UDP发送套接字
{
//ret = esp_send_broadcast_Init();
if(!ret)
{
uint8_t buf[3] = {03,03,06};
//uartSend(buf, sizeof(buf));
}
else
{
uint8_t buf[3] = {03,04,07};
uartSend(buf, sizeof(buf));
}
}
else if(res == 3)//test
{
uint8_t buf[9] = {8,8,6,6,7,6,6,8,8};
//uartSend(buf, sizeof(buf));
esp_send_broadcast(buf, 9);
}
else if(res == 4)//test2
{
uint8_t buf[10] = {1,2,3,4,5,6,7,8,9,0};
esp_send_broadcast(buf, 10);
}
else if(res == 6)//正常命令
{
esp_send_broadcast(uartRXBuf, uartRXBufLen);
}
}
}

ESP_YJM
Posts: 300
Joined: Fri Feb 26, 2021 10:30 am

Re: ESP32-S3作为STA无法同时UDP广播发送和接收

Postby ESP_YJM » Tue Nov 29, 2022 3:15 am

Code: Select all

static esp_err_t esp_send_and_recv_broadcast(void)
{
   int opt_val = 1;
   esp_err_t err = ESP_FAIL;
   struct sockaddr_in from_addr = {0};
   socklen_t from_addr_len = sizeof(struct sockaddr_in);
   char udp_recv_buf[64 + 1] = {0};

   // 创建 IPv4 UDP 套接字
   int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
   if (sockfd == -1) {
      ESP_LOGE(TAG, "Create UDP socket fail");
      return err;
   }

    // 设置广播接收地址和端口
   struct sockaddr_in server_addr = {
      .sin_family      = AF_INET,
      .sin_port        = htons(4444),
      .sin_addr.s_addr = htonl(INADDR_ANY),
   };

   int ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
   if (ret < 0) {
      ESP_LOGE(TAG, "Bind socket fail");
      goto exit;
   }

   // 设置 SO_BROADCAST 套接字选项, 使能该套接字支持广播发送
   ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt_val, sizeof(int));
   if (ret < 0) {
      ESP_LOGE(TAG, "Set SO_BROADCAST option fail");
      goto exit;
   }

   // 设置广播发送地址和端口
   struct sockaddr_in dest_addr = {
      .sin_family      = AF_INET,
      .sin_port        = htons(3333),
      .sin_addr.s_addr = htonl(INADDR_BROADCAST),
   };

   char *broadcast_msg_buf = "Are you Espressif IOT Smart Light";

   // 调用 sendto 接口发送广播数据
   ret = sendto(sockfd, broadcast_msg_buf, strlen(broadcast_msg_buf), 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
   if (ret < 0) {
      ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
   } else {
      ESP_LOGI(TAG, "Message sent successfully");
      ret = recvfrom(sockfd, udp_recv_buf, sizeof(udp_recv_buf) - 1, 0, (struct sockaddr *)&from_addr, (socklen_t *)&from_addr_len);
      if (ret > 0) {
         ESP_LOGI(TAG, "Receive udp unicast from %s:%d, data is %s", inet_ntoa(((struct sockaddr_in *)&from_addr)->sin_addr), ntohs(((struct sockaddr_in *)&from_addr)->sin_port), udp_recv_buf);
         err = ESP_OK;
      }
   }
exit:
   close(sockfd);
   return err;
}
一个 socket 就能搞定了,发送的目的端口是 3333,接收的端口是 4444。

Who is online

Users browsing this forum: No registered users and 44 guests