如何捕获客户端发送至STM32F767 TCP服务器的TCP数据包
STM32F767 TCP服务器数据捕获问题修复
核心问题分析
你的代码能返回ACK但无法捕获数据,主要是以下几个关键错误:
- 空的
tcp_echoserver_accept回调:新连接建立后,没有为该连接绑定接收回调,导致数据到达时无法触发recv_callback - 主循环中错误地给监听PCB设置
recv_callback:监听状态的TCP PCB不需要接收回调,只有已建立连接的新PCB才需要 - 未释放
pbuf:接收数据后未释放数据包缓冲区,会引发内存泄漏 - 未处理
recv_callback中的错误参数:比如连接关闭时p会为NULL,需要做相应处理
修改后的完整代码
/* USER CODE BEGIN 0 */ extern struct netif gnetif; struct tcp_pcb* tcp_echoserver_pcb; /* USER CODE END 0 */ /* USER CODE BEGIN 2 */ ip_addr_t myIPADDR; IP_ADDR4(&myIPADDR, 192, 168, 33, 1); tcp_echoserver_pcb = tcp_new(); err_t err = tcp_bind(tcp_echoserver_pcb, &myIPADDR, 8); if(err == ERR_OK) { tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb); tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept); } /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ ethernetif_input(&gnetif); sys_check_timeouts(); } /* USER CODE END 3 */ } err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { // 为新连接设置接收回调 tcp_recv(newpcb, recv_callback); // 设置连接参数(如果需要传递自定义数据) tcp_arg(newpcb, NULL); return ERR_OK; } err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { // 处理错误或连接关闭情况 if (err != ERR_OK || p == NULL) { tcp_close(tpcb); tcp_recved(tpcb, 0); return ERR_OK; } // 这里可以留存捕获到的数据,比如复制到自定义缓冲区 // 示例:将pbuf中的数据复制到全局数组 // memcpy(your_buffer, p->payload, p->len); // 发送应答(原逻辑保留) tcp_write(tpcb, p->payload, p->len, TCP_WRITE_FLAG_COPY); tcp_output(tpcb); // 通知TCP栈已处理数据 tcp_recved(tpcb, p->len); // 释放pbuf,避免内存泄漏 pbuf_free(p); return ERR_OK; }
关键修改说明
- 完善accept回调:在
tcp_echoserver_accept中为新建立的连接newpcb绑定recv_callback,这是触发数据接收的核心步骤 - 移除主循环中的错误设置:删掉主循环里的
tcp_arg和tcp_recv调用,这些操作不应该在监听PCB上执行 - 添加pbuf释放逻辑:在
recv_callback末尾调用pbuf_free(p),释放数据包占用的内存 - 错误处理:增加对
err和p的判断,处理连接异常关闭的情况 - 数据留存示例:在注释中添加了将数据复制到自定义缓冲区的示例,你可以根据需求替换成自己的存储逻辑(比如保存到数组、SD卡等)
内容的提问来源于stack exchange,提问作者confusedfresher
相关产品推荐
相关产品推荐

