protected function _Connect()
    {
        if ($this->_socket !== false) {
            // we are in persistent connection mode, so we have a socket
            // however, need to check whether it's still alive
            if (!@feof($this->_socket)) {
                return $this->_socket;
            }

            // force reopen
            $this->_socket = false;
        }

        $errno = 0;
        $errstr = '';
        $this->_connerror = false;

        if ($this->_path) {
            $host = $this->_path;
            $port = 0;
        } else {
            $host = $this->_host;
            $port = $this->_port;
        }

        if ($this->_timeout <= 0) {
            $fp = @fsockopen($host, $port, $errno, $errstr);
        } else {
            $fp = @fsockopen($host, $port, $errno, $errstr, $this->_timeout);
        }

        if (!$fp) {
            if ($this->_path) {
                $location = $this->_path;
            } else {
                $location = "{$this->_host}:{$this->_port}";
            }

            $errstr = trim($errstr);
            $this->_error = "connection to $location failed (errno=$errno, msg=$errstr)";
            $this->_connerror = true;

            return false;
        }

        // send my version
        // this is a subtle part. we must do it before (!) reading back from searchd.
        // because otherwise under some conditions (reported on FreeBSD for instance)
        // TCP stack could throttle write-write-read pattern because of Nagle.
        if (!$this->_Send($fp, pack('N', 1), 4)) {
            fclose($fp);
            $this->_error = 'failed to send client protocol version';

            return false;
        }

        // check version
        list(, $v) = unpack('N*', fread($fp, 4));
        $v = (int) $v;
        if ($v < 1) {
            fclose($fp);
            $this->_error = "expected searchd protocol version 1+, got version '$v'";

            return false;
        }

        return $fp;
    }