Make sure socket is closed after failed connection attempt.
Do not use socket.sendall() on non-blocking socket.
Define object attributes in constructor.

This prevents current and potential future KeyErrors.
Make sure heartbeat is not executed when no longer active.
Initialise connection state variables before connection attempt.

Cleanup during shutdown is less reliable if exception is thrown.