public function connect()
    {
        if ($this->connection) {
            $this->disconnect();
        }

        $hasProtocol = strpos($this->_config['host'], '://') !== false;
        if ($hasProtocol) {
            list($this->_config['protocol'], $this->_config['host']) = explode('://', $this->_config['host']);
        }
        $scheme = null;
        if (!empty($this->_config['protocol'])) {
            $scheme = $this->_config['protocol'] . '://';
        }

        $this->_setSslContext($this->_config['host']);
        if (!empty($this->_config['context'])) {
            $context = stream_context_create($this->_config['context']);
        } else {
            $context = stream_context_create();
        }

        $connectAs = STREAM_CLIENT_CONNECT;
        if ($this->_config['persistent']) {
            $connectAs |= STREAM_CLIENT_PERSISTENT;
        }

        set_error_handler([$this, '_connectionErrorHandler']);
        $this->connection = stream_socket_client(
            $scheme . $this->_config['host'] . ':' . $this->_config['port'],
            $errNum,
            $errStr,
            $this->_config['timeout'],
            $connectAs,
            $context
        );
        restore_error_handler();

        if (!empty($errNum) || !empty($errStr)) {
            $this->setLastError($errNum, $errStr);
            throw new SocketException($errStr, $errNum);
        }

        if (!$this->connection && $this->_connectionErrors) {
            $message = implode("\n", $this->_connectionErrors);
            throw new SocketException($message, E_WARNING);
        }

        $this->connected = is_resource($this->connection);
        if ($this->connected) {
            stream_set_timeout($this->connection, $this->_config['timeout']);
        }

        return $this->connected;
    }