Stop handling events if socket is closed.

Check for self.socket to ignore events on closed socket.
Remove unused variable self.fd
Define object attributes in constructor.

This prevents current and potential future KeyErrors.
Initialise connection state variables before connection attempt.

Cleanup during shutdown is less reliable if exception is thrown.
Make sure socket is closed after failed connection attempt.
Do not use socket.sendall() on non-blocking socket.
Make sure heartbeat is not executed when no longer active.