remove funky circular client/connection contract

Previously Client would call .Close() on Connection when it was disconnected,
which would close the Messages channel so that the client would stop
dispatching messages.

Now the message dispatch is registered as a callback on Connection, and when
the connection is broken, the function just inherently won't be called.

Also, now disconnection will only be noticed by the read channel, to prevent
double-registration of disconnection events. For example, the writing end will
potentially notice a disconnect when sending a large payload before the
reading end gets a chance to read the error in.