简体   繁体   中英

Sending Byte[] (TreeView) over TCP C#

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.

Code to receive the byte array:

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

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: 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

The reading loop has an issue:

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

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.

The correct way is to pass bytesReceived as offset:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM