LWIP下UDP组播协议——zynq使用,lwipudp组播zynq


  • 平台:zynq zc702 
  • LWIP : 1.4.1
  • 是否有系统: 否

一、udp基础知识:

每一个UDP连接都对应一个UDP控制块,UDP协议的实现就是对这些控制块结构成员进行操作。

为什么需要控制块链表?为了让协议栈可以实现多个连接,可以多个网络进程同时进行。最后这些控制块通过链表连接在一起。其中链接属性为外部的udp_pcbs是一个全局变量,指向控制块变量首地址。即这是一个指针变量,其数值是链表首地址。

   //定义回调函数类型
    typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
    ip_addr_t *addr, u16_t port);

    // 控制块结构体
    struct udp_pcb *next;//将控制块构成链表
    struct udp_pcb {
    IP_PCB;//宏定义IP控制块字段,使用到里面的本地IP地址和远端IP地址
    u16_t local_port, remote_port;


    u8_t flags;//状态信息

    /*
    #if LWIP_IGMP
    本地和远端端口,UDP收到报文,会遍历链表,检查本地端口号和报文中目的的端口,
    匹配成  功,那么调用对应控制块里面的函数指针处理报文。
    ip_addr_t multicast_ip;
    这样完成报文最终递交给用户程序。
    */

    #endif 

    /** receive callback function */
    #if LWIP_UDPLITE
    /** used for UDP_LITE only */
    u16_t chksum_len_rx, chksum_len_tx;
    #endif /* LWIP_UDPLITE */

    udp_recv_fn recv; //接收回调函数

    void *recv_arg; //回调函数 };

       当有多个udp用户进程时候就会产生多个udp控制块。用户进程接收数据包,用户进程发送数据包,根据目标IP和端口通过IP层发送出去;通过数据包里面的目标IP和端口选择udp控制块里面对应的回调函数。总体简单操作就是遍历控制块链表。 其中用户通过回调函数的方式被协议栈调用,这个就叫做raw/callback API。

二、LWIP之zynq-UDP组播

1. LWIP有3种编程接口

      分别为RAW,NETCONN和SOCKET。 RAW:RAW编程接口不需要操作系统的支持,可以直接裸机使用LWIP。NETCONN和SOCKET:这两种编程接口都需要有操作系统的支持。

2、组播介绍(只用UDP才有组播)

        组播地址范围是224.0.0.0到239.255.255.255。组播报文的目的地址使用D类IP地址,D类地址不能出现在IP报文的源IP地址字段。所有的信息接收者都加入到一个组内,并且一旦加入之后,流向组地址的数据立即开始向接收者传输,组中的所有成员都能接收到数据包。组播组中的成员是动态的,主机可以在任何时刻加入和离开组播组。

3、zynq7000 PS裸奔组播

 移植关键点:

(1)、打开 LWIP_IGMP 宏

 IGMP(Internet Group Management Protocol,Internet 组管理协议)是因特网协议家族中的一个组播协议。该协议运行在主机和组播路由器之间,主机通过IGMP通知路由器希望接收或离开某个特定组播组的信息。

(2)、关闭MAC层过滤功能

        在set_option中设置允许所有数据流进入,否则无法接受到组播数据,会被MAC过滤掉。

(3)、循环检测MAC层数据

        在while(1)中循环检测数据接受情况:

调用 xemacif_input(netif);

4、组播初始化代码         

void udp_Multicast(void)
{
    err_t err;
    struct udp_pcb *udppcb;
    struct ip_addr group_addr; 
    IP4_ADDR(&group_addr,239,0,1,2);  //组播池  
    
    err = igmp_joingroup(IP_ADDR_ANY,(struct ip_addr*)(&group_addr));  
    if (err != ERR_OK)
    {
        printf("igmp_joingroup error \n");
        return ;
    }
    
    udppcb = udp_new(); 
    
    if(udppcb)
    {
         udp_bind(udppcb,IP_ADDR_ANY,UDP_LOCAL_PORT);
         udp_recv(udppcb , udp_demo_recv , NULL);  
    }
       
}

   

    5、组播初始化代码     

           zynq 下默认组播是被MAC层过滤掉的,必须配置,否则,会接收不到数据。

备注:无需循环调用igmp_tmr() 函数。







版权声明:本文为博主原创文章,未经博主允许不得转载。

相关内容

    暂无相关文章