Concepts First
- UDP multicast: sends data to a group of devices that joined the same multicast group — between unicast (one-to-one) and broadcast (one-to-all); routers can forward it across subnets.
- Multicast address: IPv4 multicast addresses range from
224.0.0.0to239.255.255.255; the example uses239.0.0.1(locally administered). - IGMP: the protocol managing "who joined which group"; lwIP supports it with
LWIP_IGMP=1(enabled in the SDK by default). - IP_ADD_MEMBERSHIP:
setsockoptjoins a socket to a multicast group viastruct ip_mreq(group address + local interface).
Example Overview
The SDK has no UDP multicast example; this self-written example is built on the wifi_tcp skeleton:
- after getting an IP, creates
udp_multicast_task; - binds local port
6000and joins multicast group239.0.0.1withIP_ADD_MEMBERSHIP; - sends
hello multicastto239.0.0.1:6000every 2 seconds; - receives data from other group members and prints it.
- Related reference: to send to everyone use UDP Broadcast; point-to-point use UDP Client.
Operation Steps
The SDK has no UDP multicast example; this page is written on the wifi_tcp skeleton (marked self-written). First enter the directory:
cd examples/wifi/sta/wifi_tcpOverwrite main.c in the example directory with the self-written one below (the SDK’s lwipopts already enables LWIP_IGMP, no extra config needed):
Both Ai-M61 and Ai-M62 use bl616:
make CHIP=bl616 BOARD=bl616dkHold BOOT, briefly press EN/RST to enter download mode, then flash:
make flash CHIP=bl616 COMX=/dev/ttyUSB0Serial tool at 2000000 baud. After connecting, the program joins multicast group 239.0.0.1:6000, sends data every 2 seconds, and prints received multicast. Join the same group on another PC (e.g. nc -u 239.0.0.1 6000) to observe.
wifi_sta_connect Your_SSID 12345678Code Execution Flow
The complete UDP multicast flow from boot to send/receive:
APIs Used by the Example
setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))
Joins a multicast group. mreq is struct ip_mreq: imr_multiaddr = group 239.0.0.1, imr_interface = local interface (INADDR_ANY auto-selects).
Parameters:
sock: socket handleIP_ADD_MEMBERSHIP: join-group option
Return: 0 on success; -1 on failure
bind(sock, addr, len)
Binds local port (0.0.0.0:6000); multicast data arriving on that port is delivered to this socket.
Parameters:
sock: socket handleaddr:sockaddr_inwithhtons(6000)andINADDR_ANY
Return: 0 on success; -1 on failure
sendto / recvfrom(sock, buf, len, 0, addr, len)
Sending targets the group address 239.0.0.1:6000; receiving returns the sender's address.
Parameters:
sock: socket handleaddr/len: destination (send) / source (receive)
Return: bytes transferred; < 0 on error
Complete Code
The self-written main.c below (built on the SDK wifi_tcp skeleton; not an SDK file). Collapsed by default; click to expand:
📜 Click to expand self-written udp_multicast main.c full code
/*
* Self-written example: UDP multicast (based on lwIP sockets + IGMP)
* Usage:
* 1. Overwrite examples/wifi/sta/wifi_tcp/main.c with this file;
* 2. make CHIP=bl616 BOARD=bl616dk && make flash CHIP=bl616 COMX=/dev/ttyUSB0;
* 3. Run wifi_sta_connect <SSID> <password> on the serial shell; the program joins the group and sends/receives automatically.
*/
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include <string.h>
#include <lwip/tcpip.h>
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#include "wifi_mgmr_ext.h"
#include "fhost_api.h"
#include "wifi_mgmr.h"
#include "bflb_irq.h"
#include "bflb_uart.h"
#include "rfparam_adapter.h"
#include "async_event.h"
#include "mm.h"
#include "board.h"
#include "shell.h"
#define DBG_TAG "MAIN"
#include "log.h"
#define MULTICAST_IP "239.0.0.1"
#define MULTICAST_PORT 6000
static volatile uint32_t wifi_state = 0;
static struct bflb_device_s *uart0;
extern void shell_init_with_task(struct bflb_device_s *shell);
void wifi_event_handler(async_input_event_t ev, void *priv)
{
switch (ev->code) {
case CODE_WIFI_ON_GOT_IP:
wifi_state = 1;
LOG_I("Got IP\r\n");
break;
case CODE_WIFI_ON_DISCONNECT:
wifi_state = 0;
LOG_I("WiFi disconnected\r\n");
break;
default:
break;
}
}
static void udp_multicast_task(void *param)
{
int sock;
struct sockaddr_in local, group, remote;
struct ip_mreq mreq;
socklen_t addr_len = sizeof(remote);
char send_buf[] = "hello multicast";
char recv_buf[128];
/* Wait for Wi-Fi to get an IP */
while (!wifi_state) {
vTaskDelay(pdMS_TO_TICKS(200));
}
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
LOG_E("create socket failed\r\n");
vTaskDelete(NULL);
return;
}
/* Bind local port to receive multicast */
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(MULTICAST_PORT);
local.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, (struct sockaddr *)&local, sizeof(local)) < 0) {
LOG_E("bind failed\r\n");
}
/* Join multicast group 239.0.0.1 */
memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_IP);
mreq.imr_interface.s_addr = INADDR_ANY;
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&mreq, sizeof(mreq)) < 0) {
LOG_E("add membership failed\r\n");
}
memset(&group, 0, sizeof(group));
group.sin_family = AF_INET;
group.sin_port = htons(MULTICAST_PORT);
group.sin_addr.s_addr = inet_addr(MULTICAST_IP);
LOG_I("UDP multicast join %s:%d\r\n", MULTICAST_IP, MULTICAST_PORT);
while (1) {
int ret = sendto(sock, send_buf, strlen(send_buf), 0,
(struct sockaddr *)&group, sizeof(group));
if (ret < 0) {
LOG_E("sendto multicast failed\r\n");
} else {
LOG_I("multicast send %d bytes\r\n", ret);
}
ret = recvfrom(sock, recv_buf, sizeof(recv_buf) - 1, 0,
(struct sockaddr *)&remote, &addr_len);
if (ret >= 0) {
recv_buf[ret] = '\0';
LOG_I("recv %d bytes from %s: %s\r\n",
ret, inet_ntoa(remote.sin_addr), recv_buf);
}
vTaskDelay(pdMS_TO_TICKS(2000));
}
}
static void wifi_start_firmware_task(void *param)
{
LOG_I("Starting wifi ...\r\n");
async_register_event_filter(EV_WIFI, wifi_event_handler, NULL);
wifi_task_create();
LOG_I("Starting fhost ...\r\n");
fhost_init();
vTaskDelete(NULL);
}
int main(void)
{
board_init();
uart0 = bflb_device_get_by_name("uart0");
shell_init_with_task(uart0);
if (0 != rfparam_init(0, NULL, 0)) {
LOG_I("PHY RF init failed!\r\n");
return 0;
}
tcpip_init(NULL, NULL);
xTaskCreate(wifi_start_firmware_task, "wifi init", 1024, NULL, 10, NULL);
xTaskCreate(udp_multicast_task, "udp mcast", 1024, NULL, 11, NULL);
vTaskStartScheduler();
while (1) {
}
}FAQ
IP_ADD_MEMBERSHIP fails
Confirm LWIP_IGMP is 1 in lwipopts (SDK default); confirm bind() to the multicast port ran first; the group address must be within 224.0.0.0 ~ 239.255.255.255.
Can send but cannot receive others' multicast
Confirm both sides joined the same group and port; some routers/APs do not forward multicast by default — enable "multicast/IGMP snooping" support; verify the PC side first with nc -u 239.0.0.1 6000 on the same subnet.
Have questions?
For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

