Friday, July 22, 2016

PeekableStream, AsyncMemoryStream, NetConnection

Yesterday and today.

I've pretty much got my application transport layer functioning at levels acceptable for the prototype. I can hand off an object to my NetConnection object, and it will asynchronously serialize that object into its outgoing AsyncMemoryStream. The other side can then reconstitute it; the actual deserialization also happens on a worker thread, so all the main thread has to do is just pop off an object reference from a queue.

Yesterday things were not going well. Despite all my careful unit tests, when I did a fully assembled asynchronous test of sending objects, something was causing the stream to be garbage on the other end. Of course I was sure it must be a multithread problem--was I somehow kicking off two pool threads that were doing sends simultaneously? I fell asleep racking my brain about it.

This morning I woke up and had the answer. It wasn't a MT problem at all. I had misunderstood the expected behavior of a stream. If you tried to read 100 bytes from my AsyncMemoryStream, and there were 51 available, it would give you back 51 (the stream interface returns how many bytes are actually read). But that was wrong. You should only do a short read when you hit EndOfStream, and that's not the same as "oh there just aren't that many bytes right now".

I couldn't understand why I wasn't getting IOExceptions out of the BinaryReader that wrapped the stream, though, since that what happened when I did a trivial test, calling reader.Read(int32) with only 2 bytes in the stream. But it turns out the behavior of BinaryReader is inconsistent: if you read a string, or an int, you will get an IOException, but you try to read 'n' bytes, it will short read without error. This is explained in the MSDN docs, but I missed it. I have added in more unit tests around this.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.