def _connect(self):
        """Connect to the server."""
        assert get_thread_ident() == self.ioloop_thread_id
        if self._stream:
            self._logger.warn('Disconnecting existing connection to {0!r} '
                              'to create a new connection')
            self._disconnect()
            yield self._disconnected.until_set()

        stream = None
        try:
            host, port = self._bindaddr
            stream = self._stream = yield self._tcp_client.connect(
                host, port, max_buffer_size=self.MAX_MSG_SIZE)
            stream.set_close_callback(partial(self._stream_closed_callback,
                                              stream))
            # our message packets are small, don't delay sending them.
            stream.set_nodelay(True)
            stream.max_write_buffer_size = self.MAX_WRITE_BUFFER_SIZE
            self._logger.debug('Connected to {0} with client addr {1}'
                               .format(self.bind_address_string,
                                       address_to_string(stream.socket.getsockname())))
            if self._connect_failures >= 5:
                self._logger.warn("Reconnected to {0}"
                                  .format(self.bind_address_string))
            self._connect_failures = 0
        except Exception, e:
            if self._connect_failures % 5 == 0:
                # warn on every fifth failure

                # TODO (NM 2015-03-04) This can get a bit verbose, and typically we have
                # other mechanisms for tracking failed connections. Consider doing some
                # kind of exponential backoff starting at 5 times the reconnect time up to
                # once per 5 minutes
                self._logger.debug("Failed to connect to {0!r}: {1}"
                                  .format(self._bindaddr, e))
            self._connect_failures += 1
            stream = None
            yield gen.moment
            # TODO some kind of error rate limiting?

            if self._stream:
                # Can't use _disconnect() and wait on self._disconnected, since
                # exception may have been raised before _stream_closed_callback
                # was attached to the iostream.
                self._logger.debug('stream was set even though connecting failed')
                self._stream.close()
                self._disconnected.set()

        if stream:
            self._disconnected.clear()
            self._connected.set()
            self.last_connect_time = self.ioloop.time()
            try:
                self.notify_connected(True)
            except Exception:
                self._logger.exception("Notify connect failed. Disconnecting.")
                self._disconnect()