你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

LWIP中 udp_send(upcb, p); 之后马上调用 pbuf_free(p); 行么 ?

[复制链接]
hi201803 提问时间:2018-8-24 18:22 /
本帖最后由 hi201803 于 2018-8-24 18:56 编辑

如题:LWIP中   udp_send(upcb, p); 之后马上调用 pbuf_free(p); 行么 ?

   udp_send(upcb, p);  调用之后, 数据不一定就发出了,  至少在申请 arp解析 IP 地址时, 先要发地址解析包.
  因此     udp_send(upcb, p);  调用之后,  马上调用 pbuf_free(p);  就可能释放掉还要使用的内存.

  我的理解对么 ?

  请大侠们 指点 .

=====================================
刚才进一步查了,     在udp_send中,当调用到  etharp_query 时, 如果要解析地址, 就 把数据复制一份.
因此 udp_send 返回后,可以 立即 调用 pbuf_free(p);

=====================================

讨论: 虽然 etharp_query   把数据复制一份. 但占用多的空间.  如果 只是增加 该数据包的引用数, 应该可行  ?







收藏 评论2 发布时间:2018-8-24 18:22

举报

2个回答
feixiang20 回答时间:2018-8-24 23:35:03
针对这个问题,我也研究看了一些实例,语句可以联用,再给你个实例参考看看吧
if(flag) //your own flag to trigger event
{
               pudp_buf = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
               if(pudp_buf)
               {
                   IP4_ADDR(&dest_ip, alarm_ip[0],alarm_ip[1],
                                      alarm_ip[2],alarm_ip[3]);                 

                    memcpy(pudp_buf->payload,temp_out_buf,len);
                    err=udp_sendto(udp_comm_pcb,pudp_buf,&dest_ip,TCP_COMM_PORT);//Port to send        

                    pbuf_free(pudp_buf);
                    if(err)
                         printf("udp_sendto err!\n");
               }
  }
另外有比较长的代码也可以参考下别人的用法基于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);
}
在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);
}
在main.c文件中,在LWIP初始化之后,增加客户端初始化函数,即可实现客户端功能,实现数据回显功能。

udp_echoclient_connect();
1
3.总结

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

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

hi201803 回答时间:2018-8-25 10:12:27
本帖最后由 hi201803 于 2018-8-25 10:21 编辑
feixiang20 发表于 2018-8-24 23:35
针对这个问题,我也研究看了一些实例,语句可以联用,再给你个实例参考看看吧
if(flag) //your own flag to ...

谢谢.
另外
在使用UDP客户端时,想在配置完服务器端IP、端口号之后..... 发现在此处send数据时,源IP地址为空,

LWIP 版本 ? 在哪个地方存在bug ?

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版