I'm attempting to move an object graph from a server process to a client. And it works. At least it works when the both the client and server are on my dev virtual machine. It also works when I run the server on my base machine (client on dev vm).
It stops working though, when I run the server on my media centre PC. The exception is:
Binary stream '0' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
All three PC's are x64 Windows 7 machines. I'm using TCPClient and TCPListener along with the BinaryFormatter
class to do the heavy lifting.
The data being transferred is read from a file using a standard FileStream
object.
If at the client end I serialize the buffers to a file, the contents (according to BeyondCompare) do actually seem to differ?!?
All string properties on my objects are Base64 encoded in the setters and decoded in the getters.
I can post code but I'm not sure where the problem area lies? Any ideas?
Serialization is the process of storing the state of an object to a storage medium. In binary serialization, the public and private fields of the object and the name of the class, including the assembly containing the class, are converted to a stream of bytes, which is then written to a data stream.
The class BinaryFormatter in C# performs the actions of “serialization” and “deserialization” of binary data. It takes simple data structures such as integers (int), decimal numbers (float), and collections of letters and numbers (string) and can convert them into a binary format.
Formatter is the abstract base class for all runtime serialization formatters, and provides some helper methods for implementing the IFormatter interface.
Update: I've seemingly solved this issue. I had a breakpoint where the client read the server response
tcpClient.GetStream().Read(buffer, 0, buffer.Length);
and noted that fewer bytes were read from the "problem" server. After a quick google I found this article http://social.msdn.microsoft.com/Forums/en-US/ncl/thread/759f3f2f-347b-4bd8-aa05-fb7f681c3426 in which Dave Murray suggests:
There are a couple ways to handle this more elegantly. If you're not planning on reusing the connection for anything else, the easiest is what nobugz suggests. When the server is done sending data, have it Close() it's end of the connection. When the client has read all data sent before the Close, Read will start returning 0, at which point you know the server isn't planning on sending anything else.
So i updated my code from a single read to:
var buffer = new byte[32768];
var totalBytesRead = 0;
var bytesRead = tcpClient.GetStream().Read(buffer, 0, buffer.Length);
do
{
totalBytesRead += bytesRead;
bytesRead = tcpClient.GetStream().Read(buffer, totalBytesRead, bytesRead);
} while (bytesRead > 0);
and updated my server code to close the connection as per the post. And according to the comment from @leppie i can probably remove my Base64 wrapped properties...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With