【问题标题】:Sending Byte[] (TreeView) over TCP C#通过 TCP C# 发送 Byte[] (TreeView)
【发布时间】:2016-04-01 22:31:46
【问题描述】:

这听起来可能有点复杂,但我在计算机上有一个 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();

请记住,我还有其他用于接收图像的函数,以及使用完全相同代码的字符串,它们工作正常,所以我猜测它是因为它是一个树视图。将 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,布尔 fCheck,布尔 isCrossAppDomain,IMethodCallMessage methodCallMessage) 在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(流序列化流,HeaderHandler 处理程序,布尔 fCheck,布尔 isCrossAppDomain,IMethodCallMessage methodCallMessage) 在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)

抱歉,帖子太长了,感谢阅读,任何想法都可以理解

【问题讨论】:

  • 当您说 TreeView 时,您是指对象的层次结构,还是某种 UI 控件?
  • 窗口形式的 TreeView 显示对象的层次结构
  • 如果您想通过网络连接传输结构,我建议您创建 DTO。你在使用 WCF 吗?
  • 我只是使用 Windows 窗体,我是编程的初学者,为此我只是希望只使用 Windows 窗体,因为所有其他功能都以相同的方式通过 tcp 传输。我希望这只是一个小修复,因为它唯一的树视图在图像/字符串所在的位置不起作用
  • 不确定这是否是主要问题,但此代码 bytesReceived += stream.Read(data, 0, data.Length - bytesReceived); 存在潜在问题。将其更改为bytesReceived += stream.Read(data, bytesReceived, data.Length - bytesReceived);

标签: c# winforms serialization tcp treeview


【解决方案1】:

阅读循环有问题:

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);
}

【讨论】:

  • 我的错,当我为 OP 编写这个 sn-p 时,我错过了这一点。 ;)
  • @VisualVincent Np,它发生了 :)
猜你喜欢
  • 1970-01-01
  • 2013-07-21
  • 1970-01-01
  • 1970-01-01
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-10
相关资源
最近更新 更多