Unity中ESP32 TCP传输JSON数据拼接异常排查求助
问题定位:Unity中ESP32 TCP JSON数据拼接失败
我来帮你看看代码里的问题,你遇到的核心问题是TCP数据流的读取方式错误,导致字符串拼接被截断,下面一步步拆解:
核心错误点分析
忽略了
NetworkStream.Read()的返回值
你现在直接把整个1024字节的数组转成字符串,但Read()方法返回的是实际读取到的字节数——ESP32发送的JSON数据可能分批次传输(比如先发{,再发"capacity":100}),剩下的数组空间会被填充ASCII空字符(\0)。当你把包含空字符的数组转成字符串时,C#会把\0视为字符串结束符,所以jsonData实际上只有{,后面的内容都被截断了,拼接自然失效。字符串拼接时未处理无效空字符
即使后续读取到了有效数据,之前拼接的jsonMsg里已经包含了大量\0,后续的有效内容会被这些空字符覆盖或者无法正常显示,打印的时候只会显示到第一个\0之前的内容。
修复后的代码
我把关键部分修改好了,你可以直接替换测试:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.Net.Sockets; using System.Threading; using System.Text; [Serializable] public class SensorData { public int capacity; } public class MugSensorRead : MonoBehaviour { TcpClient client = new TcpClient(); const string IP = "192.168.137.50"; const int PORT = 5000; public SensorData sensorData; public int capacity; bool _threadRunning; Thread _thread; void Start() { client.Connect(IP, PORT); _thread = new Thread(updateSensorData); _thread.Start(); } void Update() { if (sensorData != null) { capacity = sensorData.capacity; } } void updateSensorData() { _threadRunning = true; NetworkStream stream = client.GetStream(); // 把stream提到循环外,避免重复获取 StringBuilder jsonMsgBuilder = new StringBuilder(); // 用StringBuilder提升拼接效率 while (_threadRunning) { jsonMsgBuilder.Clear(); // 每次处理新的JSON前清空 bool validJson = false; while (!validJson) { byte[] inStream = new byte[1024]; int bytesRead = stream.Read(inStream, 0, inStream.Length); // 获取实际读取的字节数 if (bytesRead <= 0) { // 连接断开的处理 _threadRunning = false; break; } // 只转换实际读取到的有效字节 string jsonData = System.Text.Encoding.ASCII.GetString(inStream, 0, bytesRead); jsonMsgBuilder.Append(jsonData); // 用StringBuilder拼接 string currentMsg = jsonMsgBuilder.ToString(); if (currentMsg.Contains("}")) { validJson = true; // 可选:截取到第一个"}"的位置,避免后续多余数据影响下一次解析 int endIndex = currentMsg.IndexOf("}") + 1; string validJsonStr = currentMsg.Substring(0, endIndex); Debug.Log("完整JSON:" + validJsonStr); sensorData = JsonUtility.FromJson<SensorData>(validJsonStr); // 把剩余的未处理数据留到下一次循环(如果有的话) if (endIndex < currentMsg.Length) { jsonMsgBuilder.Clear(); jsonMsgBuilder.Append(currentMsg.Substring(endIndex)); } } } } stream.Close(); client.Close(); } void OnDisable() { if (_threadRunning) { _threadRunning = false; _thread.Join(); } } }
额外优化说明
- 用
StringBuilder代替string.Concat:字符串是不可变类型,频繁拼接会产生大量临时对象,StringBuilder更高效。 - 将
NetworkStream提到外层循环:避免每次循环都重新获取流,减少不必要的开销。 - 增加连接断开的判断:当
bytesRead <=0时,说明TCP连接已经断开,停止线程。 - 处理多余数据:如果一次读取到多个JSON(比如
{"capacity":100}{"capacity":200}),截取第一个完整JSON后,把剩余内容留到下一次循环处理。
内容的提问来源于stack exchange,提问作者stekepego
相关产品推荐
相关产品推荐

