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