ESP32 TCP服务器能接收消息,但Android客户端无法接收消息
问题解决思路
两个核心导致挂起的原因
1. 客户端readLine()等待换行符,服务器未发送
Android客户端用BufferedReader.readLine()读取服务器响应时,这个方法会一直阻塞,直到收到**换行符\n**或者输入流关闭。但你的ESP32服务器回复的是"okay",只发送了4个字符,没有带换行符,导致客户端卡在readLine()里无限等待,表现为挂起。
修复:服务器回复时加上换行符,修改代码:
strcpy(buffer, "okay\n");
这样客户端readLine()就能正常读取到完整响应并返回。
2. 服务器字符串匹配逻辑错误+未处理带换行的输入
Android客户端用PrintWriter.println()发送消息,会自动在消息末尾添加\n,所以服务器实际收到的是"START\n",而不是你预期的"START"。
你的服务器代码里写的是:
if (strcmp("START", buffer)){ i2cMasterInit(&data); }
strcmp函数返回0表示字符串相等,非0表示不等,所以这段代码的逻辑是当收到的内容不是"START"时,才执行i2cMasterInit,但服务器日志显示收到START后执行了该函数,说明buffer里是"START\n",和"START"不相等,所以触发了这个分支,这和你的预期逻辑完全相反。
修复:
- 先处理输入的换行符,确保字符串比较准确:
// 读取数据后,去掉换行符 buffer[strcspn(buffer, "\n")] = '\0'; // 再进行相等判断 if (strcmp("START", buffer) == 0) { i2cMasterInit(&data); }
- 或者直接匹配带换行的字符串:
if (strcmp("START\n", buffer) == 0) { i2cMasterInit(&data); }
其他需要优化的点
- 服务器
read函数的安全处理:read不会自动给读取的内容加字符串结束符\0,如果读取的内容填满buffer,后续的strcmp、printf会出现未定义行为,应该预留一个字节并手动添加结束符:
n = read(sockFD, buffer, sizeof(buffer)-1); // 留一个字节给\0 if (n > 0) { buffer[n] = '\0'; }
- 处理客户端断开的情况:
当客户端正常断开时,read会返回0,需要退出循环,避免服务器无限空转:
n = read(sockFD, buffer, sizeof(buffer)-1); if (n < 0){ ESP_LOGE(TAG, "***COULD NOT READ FROM THE CLIENT***\n"); break; } else if (n == 0) { ESP_LOGI(TAG, "***CLIENT DISCONNECTED***\n"); break; } buffer[n] = '\0';
- 客户端循环逻辑优化:
客户端run函数里无限循环发送START,这会导致服务器不断重复执行i2cMasterInit,如果这不是你想要的行为,可以调整逻辑(比如只发送一次,或者根据用户操作触发发送)。
内容的提问来源于stack exchange,提问作者hugsforknife
相关产品推荐
相关产品推荐

