Reliable message send/receive
In order to reliably notify existing clients when a new client joins, we need a way to send reliably. This requires sending an acknowledgement when such messages are received, and having the sender wait with a timeout in case the message is lost.
See Gaffer on Games for some more introductory information on implementing reliable messages. Note, though, that we don't need ordered messages, we want reliable, unordered messages for now.
As of #20, an initial version of reliable message send is implemented for raw byte messages. We still need to implement support for reliable sending for serialized messages, but this will require a larger refactor to support queuing outgoing packets.