You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:02:42