2015-01-14 63 views
0

通过List<byte[]>()以下代码迭代然而问题是,由于某些原因,有时lengthBuffer是byteData的不同的大小。GetBytes会比数据返回不同大小实际上字节是

您可以在我打印BitConverter.ToInt32()长度,然后实际byteDataList[i].Length,这两个数字应该是完全一样的,有很多他们的时间DebugPrintInGame方法看,但原因不明给我很多的现在他们都没有。

与它下面这段代码发送数据的长度到服务器,因此服务器知道输入数据的大小,会发生什么,然后将其发送的实际数据。但是有时例如,它会发送长度比实际发送的数据大,但它发生随机,害得我也许认为这是一个线程问题 - 然而byteDataList是这样一个线程中仅使用,因此它没有意义对我来说,甚至可以锁定它。在我测试过的数据中,我发送的数据不超过2kb到17kb。

有谁看到为什么这可能是基于从我的项目这个小snipit发生? 此代码全部为客户端注意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]应该是相同的。

+0

是,'字节[] Array.Length'会给你的大小以字节数组的字节。 – Euthyphro

+0

是的,然后我发送该数组元素。元素的长度被发送,然后那个实际元素被发送。看看代码,注意[我]? – Euthyphro

+0

为了调试的目的,我认为你应该将字节长度加到数据数组的开始处,因为它的int表示它总是相同的长度,所以你可以在另一端读取并检查它们以确保它不是延迟/网络问题。或者你也看到打印输出中的斑点? – kmcc049

回答

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的值可能不再是您用来创建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),他们改变了这种行为,并且循环变量现在被内部作用域关闭。他们做出了这样的改变,因为在这种情况下,这个问题很容易被忽略。

+0

是的,使用.net 2.0,谢谢!现在说明为什么服务器接收的数据少于预期。 – Euthyphro

+0

@Euthyphro,你等待所有TCP数据包到达的时间足够长吗?如果您跨越数据包边界,单个接收可能无法获得所有数据,因此必须缓冲并接收数据,直到您有完整的消息。但是,在明确知道大小的情况下,大多数TCP API都会阻止您收到确切的N个字节。 –

+0

在服务器上,我没有使用.net 2.0,所以我使用'var initialBuffer = new byte [4]; var lengthBuffer = await receiveStream.ReadAsync(initialBuffer,0,4); requestLength = BitConverter.ToInt32(initialBuffer,0);'获取传入数据的长度,然后'var bytesRead = await receiveStream.ReadAsync(requestBuffer,0,requestLength);'接收基于期望长度的实际数据。这是我的理解,应该阻止和等待。如果大小不一样,我会抛出异常。 – Euthyphro

相关问题