通过 TCP C# 发送 Byte[] (TreeView)

Sending Byte[] (TreeView) over TCP C#

这听起来可能有点复杂,但我在计算机上有一个 TreeView。然后我将它转换为字节数组,通过 TCP 发送,将字节数组转换回树视图,然后再次查看它。出于某种原因,它非常有问题,完全相同的树视图可能工作一次,然后在接下来的 10 次都没有。如果 TreeView 较小,它似乎工作得更多。我知道一个事实错误是通过 tcp 发送它,因为我制作了一个程序,它只是将它转换为字节数组并返回,该程序在 100% 的时间内工作。这是代码:

byte[] data = SerilizeQueryFilters(TreeFiles); //Convert to byte[] function, 100% works fine.

stream = client.GetStream();
int length = data.Length;
byte[] datalength = new byte[4];
datalength = BitConverter.GetBytes(length);
stream.Write(datalength, 0, 4);
stream.Write(data, 0, data.Length); //Sends the byte[]

这就是服务器发送给客户端的代码。在这一点上,我不确定是不是我发错了,所以它接收错了,或者反之亦然。

接收字节数组的代码:

stream = client.GetStream();
new Thread(() =>
{
    try
    {
        while ((i = stream.Read(datalength, 0, 4)) != 0)
        {
            byte[] data = new byte[BitConverter.ToInt32(datalength, 0)];
            int bytesReceived = 0;

            while (bytesReceived < data.Length)
            {
                bytesReceived += stream.Read(data, 0, data.Length - bytesReceived);
            }
            this.Invoke((MethodInvoker)delegate
            {
                try
                {
                    if (CBCommand.SelectedItem.ToString() == "View Files")
                    {
                        DeSerilizeQueryFilters(data, TVFiles); //Convert the byte[] back into the tree view and view it
                        WriteToLog("Finished");
                    }
                }
                catch { }
            });
        }
    }
    catch { }
}).Start();

切记,我还有其他函数被遗漏用于接收图像和字符串,它们使用完全相同的代码并且它们工作正常所以我猜它是因为它是一个 treeView。将 byte[] 转换回 treeView 函数可以 100% 工作,但因为那是它搞砸的地方(因为 byte[] 已损坏或未正确发送)我将包含下面的代码

private void DeSerilizeQueryFilters(byte[] items, TreeView Treeview)
{
    BinaryFormatter bf = new BinaryFormatter();
    List<TreeNode> _list = new List<TreeNode>();
    try
    {
        using (MemoryStream ms = new MemoryStream())
        {
            ms.Write(items, 0, items.Length);
            ms.Position = 0;
            _list = bf.Deserialize(ms) as List<TreeNode>;
            Treeview.Nodes.AddRange(_list.ToArray());
        }
    }
    catch (Exception ex) { WriteToLog("Error displaying files"); Console.WriteLine(ex); }
}

所以当它失败时它会给我消息显示文件错误并写下异常以防万一:

System.Runtime.Serialization.SerializationException: 输入流不是有效的二进制格式。起始内容(以字节为单位)为:6D-73-2E-54-72-65-65-4E-6F-64-65-02-00-00-00-1D-53 ... 在 System.Runtime.Serialization.Formatters.Binary.SerializationHeaderRecord.Read(__BinaryParser 输入) 在 System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadSerializationHeaderRecord() 在 System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
在 System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler 处理程序,__BinaryParser serParser,Boolean fCheck,Boolean isCrossAppDomain,IMethodCallMessage methodCallMessage) 在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(流 serializationStream、HeaderHandler 处理程序、布尔 fCheck、布尔 isCrossAppDomain、IMethodCallMessage methodCallMessage) 在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(流序列化流)

抱歉,篇幅较长post,感谢阅读,任何想法都适用

阅读循环有问题:

while (bytesReceived < data.Length)
{
    bytesReceived += stream.Read(data, 0, data.Length - bytesReceived);
}

Stream.Read 的第二个参数是缓冲区偏移量。由于您传递的是 0(零),因此每次读取调用基本上都会覆盖之前的调用,从而以不正确的数据结束。这也解释了为什么它适用于小数据——因为如果一次读取它,一切都很好。

正确的方法是将bytesReceived作为偏移量传递:

while (bytesReceived < data.Length)
{
    bytesReceived += stream.Read(data, bytesReceived, data.Length - bytesReceived);
}