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

查看:34
本文介绍了通过 TCP C# 发送 Byte[] (TreeView)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

this may sound abit complex but i have a TreeView on a computer. I then convert it to a byte array, send it through TCP, convert the byte array back into a tree view and then view it again. For some reason its very buggy, the exact same treeview might work one time, then not for the next 10 times. It seems to work alot more if the TreeView is smaller. I know for a fact the error is from sending it through tcp because ive made a program which just converts it to byte array and back which works 100% of the time. Here is the code:

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[]

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

So thats the code from the server which sends it to the clients. at this point im not sure if im sending it wrong so its receiving it wrong or visa versa.

接收字节数组的代码:

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[] 已损坏或没有正确发送)将包含下面的代码

Bare in mind i have other functions which i left out for receiving images, and strings which use the exact same code and they work fine so im guessing its because its a treeView. Converting the byte[] back into the treeView function works 100% but as thats where its messing up (because the byte[] is corrupted or didnt send properly) ill include the code for that below

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

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

So when it fails it will give me the message error displaying files and write the exception which ill include below just in case:

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 handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)

System.Runtime.Serialization.SerializationException: The input stream is not a valid binary format. The starting contents (in bytes) are: 6D-73-2E-54-72-65-65-4E-6F-64-65-02-00-00-00-1D-53 ... at System.Runtime.Serialization.Formatters.Binary.SerializationHeaderRecord.Read(__BinaryParser input) at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadSerializationHeaderRecord() at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)

抱歉,帖子太长了,感谢阅读,任何想法都适用

Sorry about the long post, thanks for reading, any ideas are appriciated

推荐答案

阅读循环有问题:

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

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

The second argument to the Stream.Read is a buffer offset. Since you are passing 0 (zero), every read call basically overrides the previous, thus ending up with an incorrect data. This also explains why it works with small data - because if it is read in one pass, everything is fine.

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

The correct way is to pass bytesReceived as offset:

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

这篇关于通过 TCP C# 发送 Byte[] (TreeView)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆