STM32F4 LWIP UDP Demo

基于LWIP的UDP实例

本工程硬件基于STM32F429+LAN8720A外设,使用RMII通信接口。工程由STM32CUBEMX直接生成。代码主要使用的是ST官方例程。

1. 服务器端

//定义端口号
#define UDP_SERVER_PORT    7   /* define the UDP local connection port */
#define UDP_CLIENT_PORT    7   /* define the UDP remote connection port */

//声明接收数据回调函数,在初始化函数中指定
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);

//UDP服务器端初始化函数
void udp_echoserver_init(void)
{
   struct udp_pcb *upcb;
   err_t err;

   /* Create a new UDP control block  */
   upcb = udp_new();  //创建一个新的UDP控制块

   if (upcb)
   {
     /* Bind the upcb to the UDP_PORT port */
     /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
      err = udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT);   //绑定本地IP地址及端口

      if(err == ERR_OK)
      {
        /* Set a receive callback for the upcb */
        udp_recv(upcb, udp_echoserver_receive_callback, NULL);   //注册接收数据回调函数
      }
      else
      {
        udp_remove(upcb);
      }
   }
}

//服务器端接收数据回调函数
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
  /* Tell the client that we have accepted it */
    udp_sendto(upcb, p,addr,port);  //回显数据
  /* Free the p buffer */
  pbuf_free(p);
}
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

在main.c文件中,在LWIP初始化之后,增加服务器端初始化函数,即可实现服务器端功能,实现数据回显功能。

udp_echoserver_init();
    
    
  • 1

2.客户端

//接收数据回调函数声明
void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);

u8_t   data[100]={0x00}; //数据buffer初始化
__IO uint32_t message_count = 0;
struct udp_pcb *upcb;  //UDP控制块初始化

//UDP客户端连接函数
void udp_echoclient_connect(void)
{
  ip_addr_t DestIPaddr;
  err_t err;

    /*assign destination IP address */
    IP4_ADDR( &DestIPaddr, 192, 168, 1, 103 );  //设置服务器端的IP地址

  /* Create a new UDP control block  */
  upcb = udp_new();    //创建一个新的UDP控制块

  if (upcb!=NULL)
  {
    /* configure destination IP address and port */
    err= udp_connect(upcb, &DestIPaddr, 7); //服务器端地址、端口配置

    if (err == ERR_OK)
    {
            printf("local port is %d\r\n",upcb->local_port);
      /* Set a receive callback for the upcb */
      udp_recv(upcb, udp_receive_callback, NULL);  //注册回调函数
        udp_echoclient_send();   //**数据发送,第一次连接时客户端发送数据至服务器端,发送函数中会遍历查找源IP地址的配置,如果源IP地址未配置,则数据发送失败。该处出现的问题在后面总结中提到了**
    }
  }
}

//客户端数据发送函数
void udp_echoclient_send(void)
{
  struct pbuf *p;

  sprintf((char*)data, "sending udp client message %d", (int)message_count);

  /* allocate pbuf from pool*/
  p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_POOL);
  printf("test1\r\n");
  if (p != NULL)
  {
        printf("test2\r\n");
    /* copy data to pbuf */
    pbuf_take(p, (char*)data, strlen((char*)data));

    /* send udp data */
    udp_send(upcb, p);     //发送数据

    /* free pbuf */
    pbuf_free(p);
  }
    printf("test3\r\n");
}

//客户端接收数据回调函数
void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
    /* send udp data */
    udp_send(upcb, p);     //数据回显 
    /* free pbuf */
    pbuf_free(p);
}
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

在main.c文件中,在LWIP初始化之后,增加客户端初始化函数,即可实现客户端功能,实现数据回显功能。

udp_echoclient_connect();
    
    
  • 1

3.总结

  1. 基于STM32CUBEMX工具的便利性,很方便的图形化配置界面,可以直接生成需要的底层驱动代码,本次工程即直接生成了RMII+LWIP代码,主要工作放置在UDP客户端及服务器端代码的处理上。
  2. 对于生成过程中,我选择了DHCP服务,即自动获取IP地址。本来该方式是随时根据网络环境动态获取IP地址,是很便利的一种方法。但是对于我这个初学者,在使用UDP客户端时,想在配置完服务器端IP、端口号之后,向服务器端发送数据。参考了许多网上的实例都无法实现,后来使用printf打印,发现在此处send数据时,源IP地址为空,造成数据无法正常发送出去,只能在callback回调函数中进行数据发送。后面暂时去掉了DHCP服务,使用自己配置的IP则无此现象。卡了好久,做个记录。
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css">
            </div>

基于LWIP的UDP实例

本工程硬件基于STM32F429+LAN8720A外设,使用RMII通信接口。工程由STM32CUBEMX直接生成。代码主要使用的是ST官方例程。

1. 服务器端

//定义端口号
#define UDP_SERVER_PORT    7   /* define the UDP local connection port */
#define UDP_CLIENT_PORT    7   /* define the UDP remote connection port */

//声明接收数据回调函数,在初始化函数中指定
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);

//UDP服务器端初始化函数
void udp_echoserver_init(void)
{
   struct udp_pcb *upcb;
   err_t err;

   /* Create a new UDP control block  */
   upcb = udp_new();  //创建一个新的UDP控制块

   if (upcb)
   {
     /* Bind the upcb to the UDP_PORT port */
     /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
      err = udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT);   //绑定本地IP地址及端口

      if(err == ERR_OK)
      {
        /* Set a receive callback for the upcb */
        udp_recv(upcb, udp_echoserver_receive_callback, NULL);   //注册接收数据回调函数
      }
      else
      {
        udp_remove(upcb);
      }
   }
}

//服务器端接收数据回调函数
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
  /* Tell the client that we have accepted it */
    udp_sendto(upcb, p,addr,port);  //回显数据
  /* Free the p buffer */
  pbuf_free(p);
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

在main.c文件中,在LWIP初始化之后,增加服务器端初始化函数,即可实现服务器端功能,实现数据回显功能。

udp_echoserver_init();
  
  
  • 1

2.客户端

//接收数据回调函数声明
void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);

u8_t   data[100]={0x00}; //数据buffer初始化
__IO uint32_t message_count = 0;
struct udp_pcb *upcb;  //UDP控制块初始化

//UDP客户端连接函数
void udp_echoclient_connect(void)
{
  ip_addr_t DestIPaddr;
  err_t err;

    /*assign destination IP address */
    IP4_ADDR( &DestIPaddr, 192, 168, 1, 103 );  //设置服务器端的IP地址

  /* Create a new UDP control block  */
  upcb = udp_new();    //创建一个新的UDP控制块

  if (upcb!=NULL)
  {
    /* configure destination IP address and port */
    err= udp_connect(upcb, &DestIPaddr, 7); //服务器端地址、端口配置

    if (err == ERR_OK)
    {
            printf("local port is %d\r\n",upcb->local_port);
      /* Set a receive callback for the upcb */
      udp_recv(upcb, udp_receive_callback, NULL);  //注册回调函数
        udp_echoclient_send();   //**数据发送,第一次连接时客户端发送数据至服务器端,发送函数中会遍历查找源IP地址的配置,如果源IP地址未配置,则数据发送失败。该处出现的问题在后面总结中提到了**
    }
  }
}

//客户端数据发送函数
void udp_echoclient_send(void)
{
  struct pbuf *p;

  sprintf((char*)data, "sending udp client message %d", (int)message_count);

  /* allocate pbuf from pool*/
  p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_POOL);
  printf("test1\r\n");
  if (p != NULL)
  {
        printf("test2\r\n");
    /* copy data to pbuf */
    pbuf_take(p, (char*)data, strlen((char*)data));

    /* send udp data */
    udp_send(upcb, p);     //发送数据

    /* free pbuf */
    pbuf_free(p);
  }
    printf("test3\r\n");
}

//客户端接收数据回调函数
void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
    /* send udp data */
    udp_send(upcb, p);     //数据回显 
    /* free pbuf */
    pbuf_free(p);
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

在main.c文件中,在LWIP初始化之后,增加客户端初始化函数,即可实现客户端功能,实现数据回显功能。

udp_echoclient_connect();
  
  
  • 1

3.总结

  1. 基于STM32CUBEMX工具的便利性,很方便的图形化配置界面,可以直接生成需要的底层驱动代码,本次工程即直接生成了RMII+LWIP代码,主要工作放置在UDP客户端及服务器端代码的处理上。
  2. 对于生成过程中,我选择了DHCP服务,即自动获取IP地址。本来该方式是随时根据网络环境动态获取IP地址,是很便利的一种方法。但是对于我这个初学者,在使用UDP客户端时,想在配置完服务器端IP、端口号之后,向服务器端发送数据。参考了许多网上的实例都无法实现,后来使用printf打印,发现在此处send数据时,源IP地址为空,造成数据无法正常发送出去,只能在callback回调函数中进行数据发送。后面暂时去掉了DHCP服务,使用自己配置的IP则无此现象。卡了好久,做个记录。
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css">
            </div>

猜你喜欢

转载自blog.csdn.net/zhaozhiyuan111/article/details/80746174
今日推荐