GetBytes返回的实际大小与数据字节大小不同

时间:2015-01-14 21:06:40

标签: c# tcpclient netstream bitconverter

以下代码遍历List<byte[]>()但问题是由于某种原因,有时lengthBuffer与byteData的大小不同。

你可以在DebugPrintInGame方法中看到我打印BitConverter.ToInt32()长度然后是实际的byteDataList[i].Length,这两个数字应该是完全相同的,而且很多时候它们都是我现在很多时候都不知道他们现在也不知道。

使用下面的代码,它将数据的长度发送到服务器,以便服务器知道传入数据的大小和期望的内容,然后发送实际数据。但有时候例如它会发送长度大于发送的实际数据,但它会随机发生,这让我相信这可能是一个线程问题 - 尽管如此,byteDataList只在这一个线程中使用,所以对我来说甚至无法锁定它。在我测试的内容中,我发送的数据不超过2kb到17kb。

根据我项目中的这个小片断,有没有人知道为什么会发生这种情况? 此代码全部是客户端注意BitConverter.ToInt32(lengthBuffer, 0)byteDataList[i].Length预计会提供相同的长度,但事实并非如此。这就是问题所在。

List<byte[]> byteDataList = new List<byte[]>();
//.........

lock (byteDataList) //pointless lock, just used for random testing :\
{
      if (byteDataList.Count > 0)
      {
             for (int i = 0; i < byteDataList.Count; i++)
             {
                 try
                 {
                      byte[] lengthBuffer = BitConverter.GetBytes(byteDataList[i].Length);
                      //quick printout to compare lengths for testing
                      this.QueueOnMainThread(() =>
                      {
                        Tools.DebugPrintInGame("Length buffer " + lengthBuffer.Length + 
                                               +  BitConverter.ToInt32(lengthBuffer,0)+ " "+
                                               + byteDataList[i].Length);  //this should be same as BitConverter lengthBuffer
                      });
                      //send length
                      stream.Write(lengthBuffer, 0, lengthBuffer.Length);
                      //send data
                      stream.Write(byteDataList[i], 0, byteDataList[i].Length);
                      stream.Flush();
                  }
                  catch (Exception ex)
                  {
                       this.QueueOnMainThread(() =>
                       {
                           Tools.DebugPrintInGame("Exception " + ex.ToString());
                       });
                  }
             }

      }
}

在客户端打印之前,甚至将其发送到服务器:

Notice different lengths?

当最后两个应该相同时,请注意不同的长度。 即

 `lengthBuffer`    = 17672 
 `byteDataList[i]` = 17672 

但有时会变得怪异而且不稳定:

 `lengthBuffer`    = 17672
 `byteDataList[i]` = 2126

lengthBuffer和byteDataList [i]都应该是相同的。

1 个答案:

答案 0 :(得分:1)

这很可能是关闭循环中i变量的问题(我假设您使用的是.NET 4.0或更早版本?)罪魁祸首在于:

this.QueueOnMainThread(() =>
                      {
                        Tools.DebugPrintInGame("Length buffer " + lengthBuffer.Length + 
                                               +  BitConverter.ToInt32(lengthBuffer,0)+ " "+
                                               + byteDataList[i].Length);  //this should be same as BitConverter lengthBuffer
                      });

了解如何引用上面的变量i?上面的匿名方法形成了对该变量的闭包,这意味着在调用该方法之前不会对i进行求值。这意味着i的值可能不再是您用来创建lengthBuffer的值,因此会出现不匹配。

要解决此问题,请将i的副本存储到循环内部范围的变量中,如下所示:

int k = i;
this.QueueOnMainThread(() =>
                          {
                            Tools.DebugPrintInGame("Length buffer " + lengthBuffer.Length + 
                                                   +  BitConverter.ToInt32(lengthBuffer,0)+ " "+
                                                   + byteDataList[k].Length);  //this should be same as BitConverter lengthBuffer
                          });

通过关闭内部范围变量,它将具有预期值并且在循环执行时不会发生变化。这里的混淆是,为了闭包,循环变量实际上被认为超出了循环体的范围。在C#的更高版本(对于.NET 4.5)中,他们更改了此行为,现在使用内部作用域关闭循环变量。他们做出了改变,因为在这种情况下,很容易绊倒这个问题。