1

I'm making a chat system thing with tcp which requires to send things in byte arrays, but when I convert an image into a byte array, send it and then convert back it gives this error: 'End of Stream encountered before parsing was completed.'. With strings it works just fine.

    public byte[] ObjectToByteArray(object obj)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        using (var stream = new MemoryStream())
        {
            formatter.Serialize(stream, obj);
            return stream.ToArray();
        }
    }

    public object ByteArrayToObject(byte[] bytes)
    {
        using (var stream = new MemoryStream())
        {
            var binForm = new BinaryFormatter();
            stream.Write(bytes, 0, bytes.Length);
            stream.Position = 0;
            var obj = binForm.Deserialize(stream);
            return obj;
        }
    }
1
  • When wending data you the receiving side of a connection always need to know where the data ends. So you either send fixed length messages, terminate a message with a terminator (not part of message), or precede each message with a byte count. A transfer protocol usually has two layers 1) Application Layer 2) Transport Layer. Your code only has one layer. A chat application your brain can figure out where each message ends. An application you have to add what your brain does in code. Commented Oct 12, 2021 at 9:47

1 Answer 1

2

There's two separate things here; firstly, and I cannot emphasize this enough; do not use BinaryFormatter. Ever. It will hurt you. Lots of serializers exist, and BinaryFormatter (and the cousin NetDataContractSerializer) is literally the absolute last you should use. I can expand on that if you like, or I can suggest alternatives if you like.

Now; as for the actual problem: I strongly suspect that it isn't what you think it is. I have a hunch, based on decades of working on network code, that the real problem here is "framing". By which I mean: TCP is a stream protocol, not a message/packet protocol. I strongly suspect that you have not correctly deframed the exact bytes that were sent. I can't say this for sure without seeing your socket code, but... as I say: it is an hunch based on lots of experience. To investigate this: note the length of the bytes you send, and note the length of the bytes you've received. I'm pretty sure you'll find they are different. If there's still doubt: get the base-64 or hex string of the sent payload and the received payload (Convert.ToBase64String, for example), and compare that string. I'm pretty sure they'll turn out to be different.

Ultimately, network code is hard; I could try and explain individual points, but "how to correctly send messages over a network" could fill a book. IMO, if you're not interested in specializing in writing network code for the next 5 years: use an existing tool that will do the job for you, for example gRPC. Lots and lots of other messaging RPC tools exist.

Sign up to request clarification or add additional context in comments.

11 Comments

I tried the Convert.ToBase64String function but this just returns a string, I need to send an object. The only thing I could find that can do this was the BinaryFormatter which I know isn't great. I also really don't want to use external dlls which would make it way too complicated in my opinion. Also I use the functions that are in the question on both server side and client side just incase you wanted to know
@GHOST you misunderstand me; my mention of Convert.ToBase64String is just to check whether you received the exact same bytes that you sent, since it is very easy to compare strings, even by eye in a text editor. My intention was not for that to replace your existing serialization. Re the code in the question: unless I can see how you wrote and read that byte[] re the network - then that code (which I agree looks like it should work, by itself) doesn't tell me much.
@GHOST re external dlls complicating things.... well, that's massively subjective; I hear what you're saying, although personally I'm not sure how adding a NuGet package reference is inconvenient (since everything else just works), but: that's up to you. All I can say is: you have been warned (note the real details there are in the "I present my thesis" link)
Yea I had that exact thing before with serializing classes which hold the object, but it does require a dll. I want the exe to be easily sent over as an exe, this is also one of the many reasons why I don't want any dlls. I also tried ILMerge to merge the dll into the exe file but that also failed
@GHOST it sounds like what you actually want here is a "single file deployment" - see learn.microsoft.com/en-us/dotnet/core/deploying/single-file - then how that functionality is composed becomes not your problem
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.