【问题标题】:Issue returning data from Python to Unity将数据从 Python 返回到 Unity 的问题
【发布时间】:2021-03-24 22:45:12
【问题描述】:

这个问题是这个问题的演变:Issue returning header byte from Python to Unity

现在关于头字节的问题已经解决了,但是我在循环过程中遇到了问题。

数据传入良好,但在“n”次循环中断后,因为接收到一个带有开/关括号的完整数据结构的 json 字符串加上带开括号的下一个数据结构,一些数据和“图像: " 一些数据和许多 "\0" 除非右括号.. 并且 json 解析器显然会中断。为什么以及我能做什么?谢谢 下面代码修改:

IEnumerator Client()
{
   while (!IsConnected(client))
   {
      try
      {
         client = new TcpClient(host, port);                 
         s = client.GetStream();                
              
         byte[] byteBuffer = Encoding.UTF8.GetBytes("Connected to client");               
         s.Write(byteBuffer, 0, byteBuffer.Length);

         while (true)
         {
            if (s.DataAvailable)
            {            

               while (s.DataAvailable)
               { 
                  var header = new byte[4];
                  s.Read(header, 0, header.Length);
    
                  var fileSize = BitConverter.ToUInt32(header,0);

                  StringBuilder myCompleteMessage = new StringBuilder();
                  MemoryStream ms = new MemoryStream();
                       
                  int increment = 0;

                  while (ms.Length < fileSize)
                  {
                     byte[] dataReceived = new byte[fileSize];
                     increment = s.Read(dataReceived, 0, dataReceived.Length);
    
                     ms.Write(dataReceived.Take(increment).ToArray(), 0, increment);
                  }
                       
                  myCompleteMessage.AppendFormat("{0}",   Encoding.UTF8.GetString(ms.GetBuffer()));

                  JSONNode data = JSONNode.Parse(myCompleteMessage.ToString());
               
                  ....
                  // Do work with myCompleteMessage

                  yield return null;
               }
            }
         }
      }
   }
}

【问题讨论】:

  • 为什么要写"Connected to client"到socket?
  • 仅供测试

标签: python unity3d


【解决方案1】:

我这里没有你的 Unity 环境,所以我无法对此进行测试。

像这样的循环(可能在协程中运行或不会阻止 Unity 的默认处理)应该足以处理我们之前建立的形状的消息流(表示消息的 4 字节标头长度,后跟那么多字节的 JSON)。

while (!IsConnected(client))
{
    try
    {
        client = new TcpClient(host, port);
        s = client.GetStream();
        while (true)
        {
            var data = ReadPacket(s);
            // Do work with data
        }
    }
}

ReadPacket 应该类似于

JSONNode ReadPacket(Stream s)
{
    var buffer = new byte[131072];

    // Read 4 bytes (we will assume we can always read that much)
    var n = s.Read(buffer, 0, 4);
    if(n < 4) throw new Exception("short read");
    var fileSize = BitConverter.ToUInt32(buffer, 0);

    Debug.Print("Reading a blob of length", fileSize);

    // Memory stream to accumulate the reads into.    
    var ms = new MemoryStream();
    while (ms.Length < fileSize)
    {
        // Figure out how much we can read -- if we're near the end,
        // don't overread.
        var maxRead = Math.Min(buffer.Length, fileSize - ms.Length);
        var increment = s.Read(buffer, 0, maxRead);
        // ... and write them into the stream.
        ms.Write(buffer, 0, increment);
        Debug.Print("Read", ms.Length, "of", fileSize);
    }
    // Decode the bytes to UTF-8 and parse.
    return JSONNode.Parse(Encoding.UTF8.GetString(ms.GetBuffer()));
}

【讨论】:

  • 谢谢。当读取 JSONNode.Parse 返回异常时,我再次修改了代码和 Unity:异常:JSON Parse:引号似乎搞砸了。 Debug.Log:读取长度为 12120 / Read13140of12120 的 blob 我认为它会截断数据,但缓冲区仍然已满并且截断不关闭括号,并且 JSON.Parse 进入异常。
  • @Kafar 好的,我为此添加了一个错误修复 - 问题是我们总是读取到 buffer.length 个字节,这在消息末尾附近搞砸了。
  • 再次感谢。这里“var increment = s.Read(buffer, 0, maxRead);”我在“var increment = s.Read(buffer, 0, (int)maxRead);”中修改因为 Read 需要一个 int,而不是 long。但是,脚本似乎运行正常,但现在 Unity UI 的控件已冻结。
  • 您可能需要在辅助线程中运行接收循环(将接收到的 JSON 消息发布到您的主要 Unity 逻辑读取的队列中)或者作为协程运行。
  • 你想要这个循环吗?:while (ms.Length
猜你喜欢
  • 2012-11-12
  • 2013-01-24
  • 2022-12-10
  • 2014-06-20
  • 1970-01-01
  • 2016-01-08
  • 2022-01-13
  • 1970-01-01
  • 2019-10-05
相关资源
最近更新 更多