LwIP TCP接收回调异常咨询:匹配失效与乱码问题排查
TCP接收回调函数问题排查与修复
问题现象
- 首次发送数据能正常匹配返回结果,但后续发送其他内容均返回
Data could not be interpreted. - 返回消息伴随大量乱码,示例如下:
hello world hello worldJwÚ: String data was sent 111 111UUU£å©2£å©2£å©2£å©2£å©2£å©2£å©2£å©2£å©2£å©2£å©2£å©2: Data could not be interpreted. !!! !!!UUU»Ç¯»Ç¯»Ç¯»Ç¯»Ç¯»Ç¯»Ç¯»Ç¯»Ç¯»Ç¯»Ç¯»Ç¯!eÊdmu: Data could not be interpreted. hello world hello world"Æ©: String data was
问题根源
- 字符串无终止符:
memcpy只复制了数据内容,未添加\0终止符,strcmp依赖终止符判断字符串结束,后续残留数据会导致匹配失败。 - 缓冲区未清空:
data和msg应为全局/静态变量,每次使用前未清空,旧数据残留引发乱码。 - 分支代码错误:第三个分支用
sprintf(data, ...)却调用tcp_write(tpcb, msg, ...),msg未被赋值,直接使用旧内容,导致逻辑错误和乱码。 - 潜在缓冲区溢出:使用
sprintf未限制长度,可能超出缓冲区大小引发乱码。
修复后的代码
// 提前定义足够大的缓冲区,避免溢出 #define BUF_SIZE 256 static char data[BUF_SIZE]; static char msg[BUF_SIZE]; err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { if(p == NULL) { tcp_close(tpcb); return ERR_OK; } // 清空缓冲区,彻底清除旧数据残留 memset(data, 0, sizeof(data)); memset(msg, 0, sizeof(msg)); // 复制数据并添加字符串终止符,确保strcmp正常工作 if(p->len < sizeof(data)) { memcpy(data, p->payload, p->len); data[p->len] = '\0'; } else { // 数据过长时截断,避免缓冲区溢出 memcpy(data, p->payload, sizeof(data)-1); data[sizeof(data)-1] = '\0'; } // 先确认接收,防止TCP窗口阻塞,影响后续数据传输 tcp_recved(tpcb, p->len); if(strcmp(data,"111") == 0) { snprintf(msg, sizeof(msg), "%s: Integer data was sent", data); tcp_write(tpcb, msg, strlen(msg), TCP_WRITE_FLAG_COPY); } else if(strcmp(data,"hello world") == 0) { snprintf(msg, sizeof(msg), "%s: String data was sent", data); tcp_write(tpcb, msg, strlen(msg), TCP_WRITE_FLAG_COPY); } else if(strcmp(data,"!!!") == 0) { snprintf(msg, sizeof(msg), "%s: Special character data was sent", data); tcp_write(tpcb, msg, strlen(msg), TCP_WRITE_FLAG_COPY); } else { snprintf(msg, sizeof(msg), "%s: Data could not be interpreted.", data); tcp_write(tpcb, msg, strlen(msg), TCP_WRITE_FLAG_COPY); } pbuf_free(p); return ERR_OK; }
关键修复说明
- 添加字符串终止符:复制数据后手动补
\0,让strcmp能正确识别字符串边界,解决后续匹配失败问题。 - 强制清空缓冲区:每次回调开始用
memset清空缓冲区,彻底消除旧数据残留引发的乱码。 - 修正分支逻辑错误:第三个分支改为写入
msg缓冲区,不再误用变量。 - 替换为snprintf:限制写入长度,避免缓冲区溢出,提升代码安全性。
- 调整tcp_recved位置:提前确认接收,防止TCP窗口被占满,保证后续数据正常接收。
内容的提问来源于stack exchange,提问作者confusedfresher
相关产品推荐
相关产品推荐

