I hate C#, what the hell are
StreamReader supposed to be good for, except luring attention away from the classes that does the useful stuff?
You should use the classes
BinaryReader, just by knowing that you will already have grown way better at this.
With the binary classes you can simply write a bunch of floats, integers and strings, and if you run the corresponding read functions in the right order you get all the data back, so for your example you'd just:
And then to read the data:
I also don't like the choice of the polymorphic write method, you have to be careful that the data types you pass to it correspond exactly to the data types you read. Failure to do so does not even result in a runtime error, you simply get garbled data.
Binary data structures in general
The string reading and writing use a length prefix, this means that the writer starts out by writing the length of the string as an integer, followed by the plain string. The reader start out by reading the integer, and then read that number of bytes from the string. Thus there is no need for escape sequences or any such bulky workaround know from plain text file types and protocols.
The very same method can be used to build larger data structures. If for instance you'd want to send a variable number of positions followed by some other data you'd start out with an integer telling how many such positions follow, then the data structures for those positions, and then the other data. The reader then know how many such positions to read before continuing with the other data.
If need be you can build such structure in several layers with lists of objects that themselves contain lists of objects etc.
It may be a good idea to add a little room for expansion of the data format, for instance adding in a byte that must be zero at the end of an object leaves you room for adding one or more optional fields to that object thus making Dataformat v2 a superset of v1. This is mostly relevant for file formats, but I ain't going to say never for streams.
Adding a checksum, or even auto-correcting redundancy may also be a good idea, especially for files. Though TCP and UDP both employ checksums these are rather weak, so very occasionally erroneous data will slip through the internet unless a stronger error check is used.