STM32
直播中

杨火亭

8年用户 995经验值
擅长:控制/MCU
私信 关注
[问答]

STM32F429 LWIP回调函数编程问题求解

STM32F429开发板,有个无操作系统移植LWIP的例程。PC机发送一个1000字节长度的包,开发板已经完整接收到(查看tot_len =1000), 但是接收程序仅仅接收了pbuf链表的第一个pbuf数据,只有460字节,而链表后面的pbuf数据没有接收??
static err_t tcp_echoclient_recv(void *arg,struct tcp_PCB *tpcb, struct pbuf *p, err_t err)

{

         char*recdata=0;



struct echoclient *es;

err_t ret_err;





LWIP_ASSERT("arg != NULL",arg != NULL);



  es= (struct echoclient *)arg;



  if(p == NULL)  // 远程主机关闭了连接

  {

     es->state = ES_CLOSING;

     if(es->pbuf_tx == NULL)

         tcp_echoclient_connection_close(tpcb, es);

     else

         tcp_echoclient_send(tpcb, es);



     ret_err = ERR_OK;

}   

else if(err != ERR_OK)  //接收到数据,但是有错误

  {

     pbuf_free(p);

     ret_err = err;

  }

else if(es->state == ES_CONNECTED)

  {

   tcp_recved(tpcb, p->tot_len); /* 总长度 */

   recdata=(char *)malloc(p->len*sizeof(char));// 仅仅第一个长度分配空间

                   if(recdata!=NULL)

                   {

                            memcpy(recdata,p->payload,p->len);// 仅仅COPY第一个pbuf ??

     #ifdef SERIAL_DEBUG

       if(recdata!=NULL)  printf("rn%s",recdata);//

     #endif  

     free(recdata);

                   }

   pbuf_free(p);

   ret_err = ERR_OK;

  }

else  /* data received whenconnection already closed */

  {

   tcp_recved(tpcb, p->tot_len); /* Acknowledge data reception */

   pbuf_free(p);  /* free pbuf and donothing */

   ret_err = ERR_OK;

  }

  return ret_err;

}



回帖(1)

成尔秩

2024-4-26 17:36:09
在STM32F429开发板上使用LWIP进行TCP通信时,可能会遇到接收数据不完整的问题。根据您的描述,开发板已经接收到了1000字节长度的包,但是在回调函数`tcp_echoclient_recv`中,仅接收到了第一个pbuf的460字节数据,而链表后面的pbuf数据没有接收。为了解决这个问题,我们需要对回调函数进行适当的修改。

首先,我们需要了解LWIP中的pbuf结构。在LWIP中,pbuf是一种用于存储数据的内存管理结构,它可以形成一个链表,用于存储一个完整的TCP数据包。当接收到一个TCP数据包时,LWIP会将其分割成多个pbuf,并将这些pbuf通过链表连接起来。因此,为了完整地接收整个数据包,我们需要遍历整个pbuf链表。

下面是修改后的`tcp_echoclient_recv`函数的示例:

```c
static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
    char *recdata = 0;
    struct echoclient *es;
    err_t ret_err;
    LWIP_ASSERT("arg != NULL", arg != NULL);
    es = (struct echoclient *)arg;

    if (p != NULL) {
        // 计算整个数据包的长度
        u16_t data_len = 0;
        for (struct pbuf *q = p; q != NULL; q = q->next) {
            data_len += q->len;
        }

        // 分配足够大的缓冲区以存储整个数据包
        recdata = (char *)malloc(data_len);
        if (recdata == NULL) {
            // 内存分配失败
            return ERR_MEM;
        }

        // 将pbuf链表中的数据复制到缓冲区
        u16_t idx = 0;
        for (struct pbuf *q = p; q != NULL; q = q->next) {
            memcpy(&recdata[idx], q->payload, q->len);
            idx += q->len;
        }

        // 处理接收到的数据(例如,回显数据)
        // ...

        // 释放接收到的pbuf链表
        tcp_recved(tpcb, p->tot_len);
        pbuf_free(p);
    } else if (err == ERR_OK) {
        // 数据传输完成
        // ...
    } else {
        // 出现错误,处理错误情况
        // ...
    }

    return ERR_OK;
}
```

在这个修改后的函数中,我们首先计算整个数据包的长度,然后分配一个足够大的缓冲区来存储整个数据包。接下来,我们遍历pbuf链表,将每个pbuf中的数据复制到缓冲区中。最后,我们处理接收到的数据(例如,回显数据),并释放接收到的pbuf链表。

通过这种方式,我们可以确保完整地接收整个TCP数据包,而不仅仅是第一个pbuf的数据。请注意,您可能需要根据您的具体需求对上述示例进行适当的调整。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分