UDP通信

首选创建一个PCB块

struct udp_pcb* upcb;
upcb = udp_new();
// 绑定本地端口
udp_bind(upcb, IP_ADDR_ANY, 1234); 
// 连接远程端口(可省略)
udp_connect(upcb, &remote, 5555);

UDP发送:

struct pbuf *p; 
// 在POOL中分配pbuf空间(无操作系统时一般用POOL)
p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_POOL);    
if(p)
{    
    // 复制需要发送的数据到pbuf */
    pbuf_take(p, buff, len);

    // 发送数据至绑定的地址和端口    
    upd_send(upcb, p);    
    // 发送数据到指定地址和端口    
    udp_sendto(upcb, p, ipaddr, port);        
    // 指定网卡发送数据     
    udp_sendto_if(upcb, p, ipaddr, port, netif); 
}

// 释放pbuf空间(重要)
pbuf_free(p);   

UDP接收:

// 首先声明接收回调函数
void udp_recv_callback(void* arg,      // udp_recv的第3个参数
                struct udp_pcb* upcb,  // 本机描述符
                struct pbuf *p,        // 接收数据
                struct ip_addr *addr,  // 发送端IP
                uint16_t port)         // 发送端口
{
  // 将接收到的数据原路返回
  udp_sendto(upcb, p, &ipaddr, port);

  // 重要:回调函数的数据是动态申请的,一定要释放
  pbuf_free(p); 
}

// UPD接收到数据时,会调用回调函数处理,如果需要传入参数,
// 则通过第3个参数传入指针
udp_recv(upcb, udp_recv_callback, NULL);
    

重新设置IP:

// 修改网络参数前,先禁用网卡    
netif_set_down(netif);  

netif_set_ipaddr(netif,  &ipaddr);  // 设置IP地址
netif_set_netmask(netif, &netmask); // 设置子网掩码
netif_set_gw(netif, &gateway);      // 设置网关
 
// 设置全部参数(与上边的操作选一种)
// netif_set_addr(netif, &ipaddr, &netmask, &gateway);

// 修改完成后,重新启动网卡     
netif_set_up(netif);    

广播: 广播需要发送方设置BROADCAST模式,接收方无需额外设置

ip_set_option(udppcb, SOF_BROADCAST);

组播

发送组播: 发送不需要特殊设置,只需要向目地地址设置为组播地址即可。
组播地址取值范围:224.0.0.0~239.255.255.255

接收组播:

修改协议栈使能组播功能

// lwipopts.h
// 使能IGMP功能
#define LWIP_IGMP    1

// opt.h
// 添加随机接口
#include <stdlib.h>
#define LWIP_RAND() rand()

注意事项:
需要使能网卡驱动中的组播功能

stm32f4xx_hal_eth.c-->ETH_MACDMAConfig函数,修改如下:

macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE;

示例代码:

ip_addr_t group;
IP4_ADDR(&group, 224,1,1,2);    // 组播号(D类IP地址)  

// 加入组播分组
igmp_joingroup(IP_ADDR_ANY,(struct ip_addr *)(&group));   
// igmp_joingroup(&local_ip,(struct ip_addr *)(&group));

// 脱离组播分组    
igmp_leavegroup(IP_ADDR_ANY, &group);