Skip to content

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.0 to 239.255.255.255; the example uses 239.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: setsockopt joins a socket to a multicast group via struct 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 6000 and joins multicast group 239.0.0.1 with IP_ADD_MEMBERSHIP;
  • sends hello multicast to 239.0.0.1:6000 every 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

1
Enter the Example Directory

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_tcp
2
Replace main.c

Overwrite main.c in the example directory with the self-written one below (the SDK’s lwipopts already enables LWIP_IGMP, no extra config needed):

3
Build the Project

Both Ai-M61 and Ai-M62 use bl616:

make CHIP=bl616 BOARD=bl616dk
4
Flash the Firmware

Hold BOOT, briefly press EN/RST to enter download mode, then flash:

make flash CHIP=bl616 COMX=/dev/ttyUSB0
5
Connect Wi-Fi and Verify

Serial 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 12345678

Code 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 handle
  • IP_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 handle
  • addr: sockaddr_in with htons(6000) and INADDR_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 handle
  • addr / 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
c
/*
 * 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

Released under the MIT License. Build Time 2026-09-11 14:52:23