Reconnect the client after a disconnect. Can only be called after
        connect()/connect_async().

def reconnect(self):
        """Reconnect the client after a disconnect. Can only be called after
        connect()/connect_async()."""
        if len(self._host) == 0:
            raise ValueError('Invalid host.')
        if self._port <= 0:
            raise ValueError('Invalid port number.')

        self._in_packet = {
            "command": 0,
            "have_remaining": 0,
            "remaining_count": [],
            "remaining_mult": 1,
            "remaining_length": 0,
            "packet": b"",
            "to_process": 0,
            "pos": 0}

        self._out_packet_mutex.acquire()
        self._out_packet = []
        self._out_packet_mutex.release()

        self._current_out_packet_mutex.acquire()
        self._current_out_packet = None
        self._current_out_packet_mutex.release()

        self._msgtime_mutex.acquire()
        self._last_msg_in = time.time()
        self._last_msg_out = time.time()
        self._msgtime_mutex.release()

        self._ping_t = 0
        self._state_mutex.acquire()
        self._state = mqtt_cs_new
        self._state_mutex.release()
        if self._ssl:
            self._ssl.close()
            self._ssl = None
            self._sock = None
        elif self._sock:
            self._sock.close()
            self._sock = None

        # Put messages in progress in a valid state.
        self._messages_reconnect_reset()

        try:
            if (sys.version_info[0] == 2 and sys.version_info[1] < 7) or (sys.version_info[0] == 3 and sys.version_info[1] < 2):
                sock = socket.create_connection((self._host, self._port))
            else:
                sock = socket.create_connection((self._host, self._port), source_address=(self._bind_address, 0))
        except socket.error as err:
            if err.errno != errno.EINPROGRESS and err.errno != errno.EWOULDBLOCK and err.errno != EAGAIN:
                raise

        verify_hostname = self._tls_insecure is False  # Decide whether we need to verify hostname

        if self._tls_ca_certs is not None:
            if self._useSecuredWebsocket:
                # Never assign to ._ssl before wss handshake is finished
                # Non-None value for ._ssl will allow ops before wss-MQTT connection is established
                rawSSL = ssl.wrap_socket(sock, ca_certs=self._tls_ca_certs, cert_reqs=ssl.CERT_REQUIRED)  # Add server certificate verification
                rawSSL.setblocking(0)  # Non-blocking socket
                self._ssl = SecuredWebSocketCore(rawSSL, self._host, self._port, self._AWSAccessKeyIDCustomConfig, self._AWSSecretAccessKeyCustomConfig, self._AWSSessionTokenCustomConfig)  # Override the _ssl socket
                # self._ssl.enableDebug()
            elif self._alpn_protocols is not None:
                # SSLContext is required to enable ALPN support
                # Assuming Python 2.7.10+/3.5+ till the end of this elif branch
                ssl_context = SSLContextBuilder()\
                    .with_ca_certs(self._tls_ca_certs)\
                    .with_cert_key_pair(self._tls_certfile, self._tls_keyfile)\
                    .with_cert_reqs(self._tls_cert_reqs)\
                    .with_check_hostname(True)\
                    .with_ciphers(self._tls_ciphers)\
                    .with_alpn_protocols(self._alpn_protocols)\
                    .build()
                self._ssl = ssl_context.wrap_socket(sock, server_hostname=self._host, do_handshake_on_connect=False)
                verify_hostname = False  # Since check_hostname in SSLContext is already set to True, no need to verify it again
                self._ssl.do_handshake()
            else:
                self._ssl = ssl.wrap_socket(
                    sock,
                    certfile=self._tls_certfile,
                    keyfile=self._tls_keyfile,
                    ca_certs=self._tls_ca_certs,
                    cert_reqs=self._tls_cert_reqs,
                    ssl_version=self._tls_version,
                    ciphers=self._tls_ciphers)

            if verify_hostname:
                if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 5):  # No IP host match before 3.5.x
                    self._tls_match_hostname()
                else:
                    ssl.match_hostname(self._ssl.getpeercert(), self._host)

        self._sock = sock

        if self._ssl and not self._useSecuredWebsocket:
            self._ssl.setblocking(0)  # For X.509 cert mutual auth.
        elif not self._ssl:
            self._sock.setblocking(0)  # For plain socket
        else:
            pass  # For MQTT over WebSocket

        return self._send_connect(self._keepalive, self._clean_session)