Search code examples
c#serializationtcpclientnetworkstreambufferedstream

Corrupted BufferedStream when reconnecting a dropped NetworkStream


Heres the scenerio...

Server

  • I have TcpListener server that is accepting connections
  • When a connection is made, I wrap the TcpClient.GetStream() in a buffered stream.
  • Then I am using a BinaryFormatter to deserialize incoming data from the stream

Client

  • I connect to the server
  • When connected, I wrap the TcpClient.GetStream() in a buffered stream.
  • Then I use a BinaryFormatter to serialize data over the Stream.

All works wells for as long as the connection stays active. I've tested over periods of hours.

The Problem

  • Then I stop the Server to simulate a network fault (I'm using localhost)
  • The client will detect the fault (exception thrown/handled)
  • The client will re-connect later with a new TcpClient and new BufferedStream
  • The the client will use a new BinaryFormatter to start serializing data again.

Now however, the server will get all kinds of strange deserialization Exceptions. I've gone as low as looking at the bytes of the Stream and to my surprise found that the stream is being corrupted!... but only after a re-connect scenerio. And, getting rid of the BufferedStream and using the NetworkStream directly fixes the issue. You can re-connect many many times without seeing this issue.

What is going on with the BufferedStream? Every reconnect I create a new BufferedStream, but could the previous stream be affecting the new one some how?

Has anyone seen anything like this?

Unfortunatly I can't post the entire code, but here is an example of what I am doing...

Example Server Code

while (true)
{//Accept connections and spawn threads to handle incoming connections
     TcpClient connection = server.AcceptTcpClient();
}

//Done on another thread
Stream stream = new BufferedStream(connection.GetStream());
BinaryFormatter formatter = new BinaryFormatter();
object data = formatter.Deserialize(stream);

Example Client Code

_connection = new TcpClient();
_connection.Connect(_remoteAddress);
NetworkStream netStream = _connection.GetStream();
Stream stream = new BufferedStream(netStream);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, data);
stream.Flush();

Without using BufferedStream everything works ok. Also when reconnecting the above client proccess is repeated.


Solution

  • I've addressed the re-connect issue without sacrificing much speed by writting to a MemoryStream first then calling MemoryStream.WriteTo(Stream) to write the data to the non-buffered NetworkStream. This solution works, but still doesn't explain the BufferedStream issue, and is less ideal for sending large objects as the entire object has to be serialized before anything is sent.

    Still not sure what the BufferedStream issue is. And, to make it more confusing, I found out the code works flawlessly on one machine, but not on the other. Possible it's a driver issue?

    But, Serializing to a MemoryStream first then calling MemoryStream.WriteTo(Stream) works well enough for me, and runs fine on all tested machines, so I went with that.