LwIP RAW API 实现UDP多播收发

LwIP RAW API 实现UDP多播收发实现

1、初始化

static struct udp_pcb *multicast_pcb = NULL;
static ip_addr_t mutlcast_send_ip;
static ip_addr_t mutlcast_recv_ip;

static void udp_recv_multicast(void *arg, struct udp_pcb *pcb, struct pbuf *p,
    const ip_addr_t *addr, u16_t port);

static void udp_multicast_init(void)
{
    err_t err;

    if (multicast_pcb != NULL) return;

    multicast_pcb = udp_new();
    if (multicast_pcb == NULL)
    {
        LOG_LINE("udp_pcb申请失败");
        return;
    }

    IP4_ADDR(&mutlcast_send_ip, 239, 255, 255, 255);  /* 设置发送多播地址 */

    IP4_ADDR(&mutlcast_recv_ip, 239, 255, 255, 0);  /* 设置加入的多播接收地址 */

     /* 加入多播组 */
    err = igmp_joingroup(IP_ADDR_ANY, &mutlcast_recv_ip);
    if (err != ERR_OK)
    {
        LOG_LINE("加入多播组失败");
        goto free_udp_pcb;
    }

    err = udp_bind(multicast_pcb, IP_ADDR_ANY, 7770);   /* 绑定端口 */
    if (err != ERR_OK)
    {
        if (err == ERR_USE)
        {
            LOG_LINE("IP地址或端口已经被使用");
        }
        LOG_LINE("绑定IP、端口失败");
        goto free_udp_pcb;
    }

    udp_recv(multicast_pcb, udp_recv_multicast, NULL);
    
    LOG_LINE("组播初始化");
    return;
free_udp_pcb:
    udp_remove(multicast_pcb);
}

2、多播发送

int udp_multicast_send(const void *psrc, uint32_t src_len, uint16_t port)
{
    struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, src_len, PBUF_POOL);
    if (p == NULL)
    {
        LOG_LINE("pbuf申请失败");
        return -1;
    }
    pbuf_take(p, psrc, src_len);
    udp_sendto(multicast_pcb, p, &mutlcast_send_ip, port);
    pbuf_free(p);  /* 释放pbuf */
    return 0;
}

3、多播接收

static char recv_multicast_buf[1024] = {0};
void udp_recv_multicast(void *arg, struct udp_pcb *pcb, struct pbuf *p,
    const ip_addr_t *addr, u16_t port)
{
    struct pbuf *q;
    int recv_count = 0;
    struct ip4_addr_fmt {
        uint32_t addr1 : 8;
        uint32_t addr2 : 8;
        uint32_t addr3 : 8;
        uint32_t addr4 : 8;
    };

    for (q = p; q != NULL; q = p->next)
    {
        if (q->len > sizeof(recv_multicast_buf))
        {
            memcpy(recv_multicast_buf, q->payload, sizeof(recv_multicast_buf));
            LOG_LINE("数据溢出, 截断接收");
            return;
        }
        else 
        {
            if (recv_count < sizeof(recv_multicast_buf))
            {
                rt_memcpy(&recv_multicast_buf[recv_count], q->payload, q->len);
                recv_count += q->len;
            }
            else
            {
                LOG_LINE("数据溢出, 截断接收");
                return;
            }
        }
    }
    // uint32_t ip = addr->addr;
    struct ip4_addr_fmt *ip = (struct ip4_addr_fmt *)addr;
    LOG_LINE("multicast recv from %d.%d.%d.%d/%d, msg %s", 
            ip->addr1, ip->addr2, ip->addr3, ip->addr4, port, recv_multicast_buf);
}

通过UDP接收回调函数接收数据保存到buffer。
这里只是将接收的消息打印出来。

测试

组播发送测试:
打开网络调试助手,设置好监听端口号,板子程序通过什么端口号发送,这里就设置为相应的端口号。
在这里插入图片描述
前面初始化程序发送设置的多播组是239.255.255.255 ,往7777端口发送数据,所以这里设置端口号为7777

测试程序:

static char fmt_buf[10] = {0};
static uint16_t test_count = 0;
void btn_long_press_start(void *p_btn)
{
    struct Button *btn = (struct Button *)p_btn;
    switch (btn->button_id)
    {
        case BTN_ID_SYS_TEST:  /* 测试键 */

            break;
        case BTN_ID_CARD_OUT:  /* 强制退卡键 */
            rt_snprintf(fmt_buf, sizeof(fmt_buf), "test %d", ++test_count);
            udp_multicast_send(fmt_buf, rt_strlen(fmt_buf), 7777);
            LOG_LINE("退卡键长按 %s", fmt_buf);
            rt_memset(fmt_buf, 0, sizeof(fmt_buf));
            break;
        default:
            LOG_LINE("don't have this key");
            break;
    }
}

在这里插入图片描述
组播接收测试:
网络调试助手设置组播地址和远程地址、端口
在这里插入图片描述
板子程序接收数据加入的多播组是239.255.255.0,端口号是7770 ,IP地址是192.168.57.101

点击网络调试助手发送,串口调试助手打印出接收的数据
在这里插入图片描述

参考:

网络编程:用UDP通信实现组播通信(多播)_udp组播通信_qq_42343682的博客-CSDN博客

UDP局域网内广播消息_udp广播网段192.168.0.255_changeyourmind的博客

STM32F4板子使用LWIP进行组播收发数据的完整过程,附代码_lwip组播_纵横千里,捭阖四方的博客-CSDN博客

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欲盖弥彰1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值