关于lwip的pbuf数据提取问题

版本vivado 2018.4
lwip202 版本:1.2
我用的是sdk中lwip echo模板做的,想提取从PC接收到的数据包数据,但是提取出来的数据跟我发的严重不符,求解答
这个是我发送的界面,只发02,可以看到回调函数(echo)触发正常,整体收发是没问题的

img


但是串口返回的SDK解析出来的数据就离谱了:

img

源码如下:

err_t recv_callback(void *arg, struct tcp_pcb *tpcb,
                               struct pbuf *p, err_t err)
{
    /* do not read the packet if we are not in ESTABLISHED state */
    if (!p) {
        tcp_close(tpcb);
        tcp_recv(tpcb, NULL);
        return ERR_OK;
    }
    int k=0;
    int rev;
    /* indicate that the packet has been received */
    tcp_recved(tpcb, p->len); //这是监听后,接收到的pbuf结构
    struct pbuf *q;
    for(q = p; q != NULL; q = q->next) {
        xil_printf("data is: %d\n", (int *) q->payload);
    }//打印接收到的数据
    if (tcp_sndbuf(tpcb) > packet->len) {
        err = tcp_write(tpcb, p->payload, p->len, 1);
    } else
        xil_printf("no space in tcp_sndbuf\n\r");

    pbuf_free(p);

    return ERR_OK;
}


如果有好的代码或方法更好,最好是能把接收到的数据存到一个指针里,谢谢各位!

引用chatgpt部分指引作答:
根据你提供的代码,我看到你正在使用lwIP库来实现TCP/IP通信,并且你的回调函数中的代码似乎有一些问题。

在你的回调函数中,你使用了一个循环来遍历pbuf链表,并打印每个pbuf的payload数据。然而,在打印数据时,你将q->payload强制转换为int类型并打印,这是不正确的。q->payload实际上是一个void类型的指针,指向接收到的数据缓冲区。

为了正确打印接收到的数据,你应该使用memcpy函数将q->payload的数据复制到一个缓冲区中,并将缓冲区作为字符串打印出来。这样做可以避免类型转换错误,并确保正确提取和打印数据。

以下是修改后的代码示例:

err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
    if (!p) {
        tcp_close(tpcb);
        tcp_recv(tpcb, NULL);
        return ERR_OK;
    }

    tcp_recved(tpcb, p->tot_len); // 更新接收窗口大小

    char buffer[p->tot_len + 1]; // 创建缓冲区用于存储接收到的数据
    memset(buffer, 0, sizeof(buffer)); // 清空缓冲区

    struct pbuf *q;
    int offset = 0;

    // 将接收到的数据复制到缓冲区中
    for (q = p; q != NULL; q = q->next) {
        memcpy(buffer + offset, q->payload, q->len);
        offset += q->len;
    }

    xil_printf("Received data: %s\n", buffer); // 打印接收到的数据

    if (tcp_sndbuf(tpcb) > p->len) {
        err = tcp_write(tpcb, p->payload, p->len, 1);
    } else {
        xil_printf("No space in tcp_sndbuf\n\r");
    }

    pbuf_free(p);

    return ERR_OK;
}

在修改后的代码中,我创建了一个名为buffer的字符数组,大小为接收到的数据的总长度加1。然后,我使用memcpy函数将每个pbuf的数据复制到buffer中,并在打印时将buffer作为字符串传递给xil_printf函数。

这样,你应该能够正确提取并打印从PC接收到的数据了。请注意,这个修改只是针对数据的提取和打印部分,其他代码可能还需要根据你的需求进行调整。

你打印的是 q->payload,这个是接收数据的指针(而且可能只是其中的一段)并不是数据本身,当然不对了,这种底层的用法,你要了解pbuf的链表结构,可以先用下面的代码,把所有数据放到一个buffer,然后挨个打印buffer里的数据,buffer里不一定是字符串,所以不建议直接用字符串方式输出。

 for (q = p; q != NULL; q = q->next) {
        memcpy(buffer + offset, q->payload, q->len);
        offset += q->len;
    }

for(i = 0; i< offset; i++){
  printf("%02x ",  * (buffer + i));//以十六进制方式展示数据
}

当然,也可以不用先拷出来,直接就打印

 for (q = p; q != NULL; q = q->next) {
        for(i = 0; i< q->len; i++)
          printf("%02x ",  * (q->payload + i));//以十六进制方式展示数据
    }

上述代码代替你代码里的15-17行输出