用JAVA 源码角度看 客户端请求服务器流程中地址是域名情况下解析域名流程

news/2025/1/8 11:48:38 标签: java, 服务器, 开发语言

1. 域名解析的入口点

  • getaddrinfo 或 getAllByName 方法:在底层,Java 使用 getaddrinfo(在 Unix-like 系统中)或类似的系统调用来解析域名。在 Java 的 InetAddress 类中,getAllByName 方法是解析域名的入口点之一。它会调用 getAddressesFromNameService 方法来获取域名对应的 IP 地址列表。

2. getAddressesFromNameService 方法

  • 调用 nameService.lookupAllHostAddr:此方法尝试通过注册的 NameService(如 PlatformNameService)来解析域名。PlatformNameService 是一个内部类,它实现了 NameService 接口,并调用 impl.lookupAllHostAddr 方法来执行实际的域名解析。
  • 处理异常:如果解析失败,会抛出 UnknownHostException。对于 "localhost" 这样的特殊情况,会直接返回回环地址。
  • 处理请求地址:如果指定了请求地址 (reqAddr),则会检查解析结果中是否包含该地址,并进行相应的处理(如旋转数组).

3. lookupAllHostAddr 方法

  • 本地缓存和系统缓存:在某些实现中,可能会先检查本地缓存或系统缓存,以快速获取域名对应的 IP 地址。
  • 调用底层系统调用:最终,会调用底层的系统调用(如 getaddrinfo)来从 DNS 服务器获取域名对应的 IP 地址列表。这个过程可能涉及与本地 DNS 服务器的通信,以及 DNS 服务器之间的查询转发.

4. plainConnect 和 plainConnect0 方法

  • 权限检查:在 plainConnect 方法中,会先检查是否已经连接。如果未连接,则会进行权限检查,确保有权限连接到指定的 URL。
  • 使用缓存:在 plainConnect0 方法中,会尝试从本地缓存中获取响应。如果缓存命中且满足条件(如不是 HTTPS 请求),则会直接使用缓存的响应,而不需要进行实际的网络连接。
  • 代理选择:如果没有缓存命中,则会根据配置选择合适的代理(如实例代理或系统默认代理)。如果没有代理或代理连接失败,则会尝试直接连接。
  • 创建 HTTP 客户端:通过 getNewHttpClient 方法创建一个新的 HTTP 客户端,并设置连接超时和读取超时等参数。
  • 打开服务器连接:调用 openServer 方法来打开与远程服务器的连接。如果使用代理,则会通过代理服务器进行连接。

5. openServer 方法

  • 安全检查:如果存在安全管理器,则会进行连接权限检查。
  • 处理代理:如果使用代理,则会根据代理类型(如 HTTP 代理或 SOCKS 代理)进行相应的处理。对于 HTTP 代理,会调用 privilegedOpenServer 方法来通过代理服务器建立连接。
  • 直接连接:如果没有代理或代理连接失败,则会直接连接到远程服务器。调用 super.openServer 方法来执行实际的连接操作.

总结

Java 客户端请求流程中解析域名的过程涉及多个层次的处理,从 InetAddress 类的高层方法到底层的系统调用。通过缓存、代理选择和权限检查等机制,Java 能够灵活地处理各种网络环境下的域名解析和连接请求。这个过程确保了客户端能够高效、安全地与远程服务器进行通信。

##实验代码

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpUrlConnectionDemo {

    public static void main(String[] args) {
        try {
            // 创建URL对象
            URL url = new URL("http://www.baidu.com");
            // 打开连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 设置请求方法为GET
            connection.setRequestMethod("GET");
            // 设置超时时间
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);

            // 获取响应码
            int responseCode = connection.getResponseCode();
            System.out.println("Response Code: " + responseCode);

            // 如果响应成功,则读取响应内容
            if (responseCode == HttpURLConnection.HTTP_OK) { // 200表示成功
                BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String inputLine;
                StringBuilder content = new StringBuilder();

                while ((inputLine = in.readLine()) != null) {
                    content.append(inputLine);
                }

                // 关闭流
                in.close();
                // 输出响应内容
                System.out.println("Response Content: " + content.toString());
            } else {
                System.out.println("GET request not worked");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

##java源码

protected void plainConnect()  throws IOException {
        synchronized (this) {
            if (connected) {
                return;
            }
        }
        SocketPermission p = URLtoSocketPermission(this.url);
        if (p != null) {
            try {
                AccessController.doPrivilegedWithCombiner(
                    new PrivilegedExceptionAction<>() {
                        public Void run() throws IOException {
                            plainConnect0();
                            return null;
                        }
                    }, null, p
                );
            } catch (PrivilegedActionException e) {
                    throw (IOException) e.getException();
            }
        } else {
            // run without additional permission
            plainConnect0();
        }
    }

protected void plainConnect0()  throws IOException {
        // try to see if request can be served from local cache
        if (cacheHandler != null && getUseCaches()) {
            try {
                URI uri = ParseUtil.toURI(url);
                if (uri != null) {
                    cachedResponse = cacheHandler.get(uri, getRequestMethod(), getUserSetHeaders().getHeaders());
                    if ("https".equalsIgnoreCase(uri.getScheme())
                        && !(cachedResponse instanceof SecureCacheResponse)) {
                        cachedResponse = null;
                    }
                    if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
                        logger.finest("Cache Request for " + uri + " / " + getRequestMethod());
                        logger.finest("From cache: " + (cachedResponse != null ? cachedResponse.toString() : "null"));
                    }
                    if (cachedResponse != null) {
                        cachedHeaders = mapToMessageHeader(cachedResponse.getHeaders());
                        cachedInputStream = cachedResponse.getBody();
                    }
                }
            } catch (IOException ioex) {
                // ignore and commence normal connection
            }
            if (cachedHeaders != null && cachedInputStream != null) {
                connected = true;
                return;
            } else {
                cachedResponse = null;
            }
        }
        try {
            /* Try to open connections using the following scheme,
             * return on the first one that's successful:
             * 1) if (instProxy != null)
             *        connect to instProxy; raise exception if failed
             * 2) else use system default ProxySelector
             * 3) else make a direct connection if ProxySelector is not present
             */

            if (instProxy == null) { // no instance Proxy is set
                /**
                 * Do we have to use a proxy?
                 */
                ProxySelector sel =
                    java.security.AccessController.doPrivileged(
                        new java.security.PrivilegedAction<>() {
                            public ProxySelector run() {
                                     return ProxySelector.getDefault();
                                 }
                             });
                if (sel != null) {
                    URI uri = sun.net.www.ParseUtil.toURI(url);
                    if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
                        logger.finest("ProxySelector Request for " + uri);
                    }
                    Iterator<Proxy> it = sel.select(uri).iterator();
                    Proxy p;
                    while (it.hasNext()) {
                        p = it.next();
                        try {
                            if (!failedOnce) {
                                http = getNewHttpClient(url, p, connectTimeout);
                                http.setReadTimeout(readTimeout);
                            } else {
                                // make sure to construct new connection if first
                                // attempt failed
                                http = getNewHttpClient(url, p, connectTimeout, false);
                                http.setReadTimeout(readTimeout);
                            }
                            if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
                                if (p != null) {
                                    logger.finest("Proxy used: " + p.toString());
                                }
                            }
                            break;
                        } catch (IOException ioex) {
                            if (p != Proxy.NO_PROXY) {
                                sel.connectFailed(uri, p.address(), ioex);
                                if (!it.hasNext()) {
                                    if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
                                        logger.finest("Retrying with proxy: " + p.toString());
                                    }
                                    http = getNewHttpClient(url, p, connectTimeout, false);
                                    http.setReadTimeout(readTimeout);
                                    break;
                                }
                            } else {
                                throw ioex;
                            }
                            continue;
                        }
                    }
                } else {
                    // No proxy selector, create http client with no proxy
                    if (!failedOnce) {
                        http = getNewHttpClient(url, null, connectTimeout);
                        http.setReadTimeout(readTimeout);
                    } else {
                        // make sure to construct new connection if first
                        // attempt failed
                        http = getNewHttpClient(url, null, connectTimeout, false);
                        http.setReadTimeout(readTimeout);
                    }
                }
            } else {
                if (!failedOnce) {
                    http = getNewHttpClient(url, instProxy, connectTimeout);
                    http.setReadTimeout(readTimeout);
                } else {
                    // make sure to construct new connection if first
                    // attempt failed
                    http = getNewHttpClient(url, instProxy, connectTimeout, false);
                    http.setReadTimeout(readTimeout);
                }
            }

            ps = (PrintStream)http.getOutputStream();
        } catch (IOException e) {
            throw e;
        }
        // constructor to HTTP client calls openserver
        connected = true;
    }

protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout)
        throws IOException {
        return HttpClient.New(url, p, connectTimeout, this);
    }

protected synchronized void openServer() throws IOException {

        SecurityManager security = System.getSecurityManager();

        if (security != null) {
            security.checkConnect(host, port);
        }

        if (keepingAlive) { // already opened
            return;
        }

        if (url.getProtocol().equals("http") ||
            url.getProtocol().equals("https") ) {

            if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {
                sun.net.www.URLConnection.setProxiedHost(host);
                privilegedOpenServer((InetSocketAddress) proxy.address());
                usingProxy = true;
                return;
            } else {
                // make direct connection
                openServer(host, port);
                usingProxy = false;
                return;
            }

        } else {
            /* we're opening some other kind of url, most likely an
             * ftp url.
             */
            if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {
                sun.net.www.URLConnection.setProxiedHost(host);
                privilegedOpenServer((InetSocketAddress) proxy.address());
                usingProxy = true;
                return;
            } else {
                // make direct connection
                super.openServer(host, port);
                usingProxy = false;
                return;
            }
        }
    }

public void openServer(String server, int port) throws IOException {
        serverSocket = doConnect(server, port);
        try {
            OutputStream out = serverSocket.getOutputStream();
            if (capture != null) {
                out = new HttpCaptureOutputStream(out, capture);
            }
            serverOutput = new PrintStream(
                new BufferedOutputStream(out),
                                         false, encoding);
        } catch (UnsupportedEncodingException e) {
            throw new InternalError(encoding+" encoding not found", e);
        }
        serverSocket.setTcpNoDelay(true);
    }

protected Socket doConnect (String server, int port)
    throws IOException, UnknownHostException {
        Socket s;
        if (proxy != null) {
            if (proxy.type() == Proxy.Type.SOCKS) {
                s = AccessController.doPrivileged(
                    new PrivilegedAction<>() {
                        public Socket run() {
                                       return new Socket(proxy);
                                   }});
            } else if (proxy.type() == Proxy.Type.DIRECT) {
                s = createSocket();
            } else {
                // Still connecting through a proxy
                // server & port will be the proxy address and port
                s = new Socket(Proxy.NO_PROXY);
            }
        } else {
            s = createSocket();
        }

        // Instance specific timeouts do have priority, that means
        // connectTimeout & readTimeout (-1 means not set)
        // Then global default timeouts
        // Then no timeout.
        if (connectTimeout >= 0) {
            s.connect(new InetSocketAddress(server, port), connectTimeout);
        } else {
            if (defaultConnectTimeout > 0) {
                s.connect(new InetSocketAddress(server, port), defaultConnectTimeout);
            } else {
                s.connect(new InetSocketAddress(server, port));
            }
        }
        if (readTimeout >= 0)
            s.setSoTimeout(readTimeout);
        else if (defaultSoTimeout > 0) {
            s.setSoTimeout(defaultSoTimeout);
        }
        return s;
    }

public static InetAddress[] getAllByName(String host)
        throws UnknownHostException {
        return getAllByName(host, null);
    }

private static InetAddress[] getAllByName(String host, InetAddress reqAddr)
        throws UnknownHostException {

        if (host == null || host.isEmpty()) {
            InetAddress[] ret = new InetAddress[1];
            ret[0] = impl.loopbackAddress();
            return ret;
        }

        validate(host);
        boolean ipv6Expected = false;
        if (host.charAt(0) == '[') {
            // This is supposed to be an IPv6 literal
            if (host.length() > 2 && host.charAt(host.length()-1) == ']') {
                host = host.substring(1, host.length() -1);
                ipv6Expected = true;
            } else {
                // This was supposed to be a IPv6 literal, but it's not
                throw invalidIPv6LiteralException(host, false);
            }
        }

        // Check and try to parse host string as an IP address literal
        if (IPAddressUtil.digit(host.charAt(0), 16) != -1
            || (host.charAt(0) == ':')) {
            byte[] addr = null;
            int numericZone = -1;
            String ifname = null;
            if (!ipv6Expected) {
                // check if it is IPv4 address only if host is not wrapped in '[]'
                try {
                    addr = IPAddressUtil.validateNumericFormatV4(host);
                } catch (IllegalArgumentException iae) {
                    var uhe = new UnknownHostException(host);
                    uhe.initCause(iae);
                    throw uhe;
                }
            }
            if (addr == null) {
                // Try to parse host string as an IPv6 literal
                // Check if a numeric or string zone id is present first
                int pos;
                if ((pos = host.indexOf('%')) != -1) {
                    numericZone = checkNumericZone(host);
                    if (numericZone == -1) { /* remainder of string must be an ifname */
                        ifname = host.substring(pos + 1);
                    }
                }
                if ((addr = IPAddressUtil.textToNumericFormatV6(host)) == null &&
                        (host.contains(":") || ipv6Expected)) {
                    throw invalidIPv6LiteralException(host, ipv6Expected);
                }
            }
            if(addr != null) {
                InetAddress[] ret = new InetAddress[1];
                if (addr.length == Inet4Address.INADDRSZ) {
                    if (numericZone != -1 || ifname != null) {
                        // IPv4-mapped address must not contain zone-id
                        throw new UnknownHostException(host + ": invalid IPv4-mapped address");
                    }
                    ret[0] = new Inet4Address(null, addr);
                } else {
                    if (ifname != null) {
                        ret[0] = new Inet6Address(null, addr, ifname);
                    } else {
                        ret[0] = new Inet6Address(null, addr, numericZone);
                    }
                }
                return ret;
            }
        } else if (ipv6Expected) {
            // We were expecting an IPv6 Literal since host string starts
            // and ends with square brackets, but we got something else.
            throw invalidIPv6LiteralException(host, true);
        }
        return getAllByName0(host, reqAddr, true, true);
    }

static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr)
        throws UnknownHostException
    {
        InetAddress[] addresses = null;
        UnknownHostException ex = null;
        validate(host);

            try {
                addresses = nameService.lookupAllHostAddr(host);
            } catch (UnknownHostException uhe) {
                if (host.equalsIgnoreCase("localhost")) {
                    addresses = new InetAddress[] { impl.loopbackAddress() };
                }
                else {
                    ex = uhe;
                }
            }

        if (addresses == null) {
            throw ex == null ? new UnknownHostException(host) : ex;
        }

        // More to do?
        if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) {
            // Find it?
            int i = 1;
            for (; i < addresses.length; i++) {
                if (addresses[i].equals(reqAddr)) {
                    break;
                }
            }
            // Rotate
            if (i < addresses.length) {
                InetAddress tmp, tmp2 = reqAddr;
                for (int j = 0; j < i; j++) {
                    tmp = addresses[j];
                    addresses[j] = tmp2;
                    tmp2 = tmp;
                }
                addresses[i] = tmp2;
            }
        }

        return addresses;
    }

private static final class PlatformNameService implements NameService {

        public InetAddress[] lookupAllHostAddr(String host)
            throws UnknownHostException
        {
            return impl.lookupAllHostAddr(host);
        }

        public String getHostByAddr(byte[] addr)
            throws UnknownHostException
        {
            return impl.getHostByAddr(addr);
        }
    }

public native InetAddress[] lookupAllHostAddr(String hostname)
        throws UnknownHostException;

##openjdk17 对应解析域名的  C++源码。error = getaddrinfo(hostname, NULL, &hints, &res);

/*
 * Class:     java_net_Inet6AddressImpl
 * Method:    lookupAllHostAddr
 * Signature: (Ljava/lang/String;)[[B
 */
JNIEXPORT jobjectArray JNICALL
Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
                                                 jstring host) {
    jobjectArray ret = NULL;
    const char *hostname;
    int error = 0;
    struct addrinfo hints, *res = NULL, *resNew = NULL, *last = NULL,
        *iterator;

    initInetAddressIDs(env);
    JNU_CHECK_EXCEPTION_RETURN(env, NULL);

    if (IS_NULL(host)) {
        JNU_ThrowNullPointerException(env, "host argument is null");
        return NULL;
    }
    hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
    CHECK_NULL_RETURN(hostname, NULL);

    // try once, with our static buffer
    memset(&hints, 0, sizeof(hints));
    hints.ai_flags = AI_CANONNAME;
    hints.ai_family = AF_UNSPEC;

    error = getaddrinfo(hostname, NULL, &hints, &res);

    if (error) {
#if defined(MACOSX)
        // if getaddrinfo fails try getifaddrs
        ret = lookupIfLocalhost(env, hostname, JNI_TRUE);
        if (ret != NULL || (*env)->ExceptionCheck(env)) {
            goto cleanupAndReturn;
        }
#endif
        // report error
        NET_ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
        goto cleanupAndReturn;
    } else {
        int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0,
            inet6Index = 0, originalIndex = 0;
        int addressPreference =
            (*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID);;
        iterator = res;
        while (iterator != NULL) {
            // skip duplicates
            int skip = 0;
            struct addrinfo *iteratorNew = resNew;
            while (iteratorNew != NULL) {
                if (iterator->ai_family == iteratorNew->ai_family &&
                    iterator->ai_addrlen == iteratorNew->ai_addrlen) {
                    if (iteratorNew->ai_family == AF_INET) { /* AF_INET */
                        struct sockaddr_in *addr1, *addr2;
                        addr1 = (struct sockaddr_in *)iterator->ai_addr;
                        addr2 = (struct sockaddr_in *)iteratorNew->ai_addr;
                        if (addr1->sin_addr.s_addr == addr2->sin_addr.s_addr) {
                            skip = 1;
                            break;
                        }
                    } else {
                        int t;
                        struct sockaddr_in6 *addr1, *addr2;
                        addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
                        addr2 = (struct sockaddr_in6 *)iteratorNew->ai_addr;

                        for (t = 0; t < 16; t++) {
                            if (addr1->sin6_addr.s6_addr[t] !=
                                addr2->sin6_addr.s6_addr[t]) {
                                break;
                            }
                        }
                        if (t < 16) {
                            iteratorNew = iteratorNew->ai_next;
                            continue;
                        } else {
                            skip = 1;
                            break;
                        }
                    }
                } else if (iterator->ai_family != AF_INET &&
                           iterator->ai_family != AF_INET6) {
                    // we can't handle other family types
                    skip = 1;
                    break;
                }
                iteratorNew = iteratorNew->ai_next;
            }

            if (!skip) {
                struct addrinfo *next
                    = (struct addrinfo *)malloc(sizeof(struct addrinfo));
                if (!next) {
                    JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
                    ret = NULL;
                    goto cleanupAndReturn;
                }
                memcpy(next, iterator, sizeof(struct addrinfo));
                next->ai_next = NULL;
                if (resNew == NULL) {
                    resNew = next;
                } else {
                    last->ai_next = next;
                }
                last = next;
                i++;
                if (iterator->ai_family == AF_INET) {
                    inetCount++;
                } else if (iterator->ai_family == AF_INET6) {
                    inet6Count++;
                }
            }
            iterator = iterator->ai_next;
        }

        // allocate array - at this point i contains the number of addresses
        ret = (*env)->NewObjectArray(env, i, ia_class, NULL);
        if (IS_NULL(ret)) {
            /* we may have memory to free at the end of this */
            goto cleanupAndReturn;
        }

        if (addressPreference == java_net_InetAddress_PREFER_IPV6_VALUE) {
            inetIndex = inet6Count;
            inet6Index = 0;
        } else if (addressPreference == java_net_InetAddress_PREFER_IPV4_VALUE) {
            inetIndex = 0;
            inet6Index = inetCount;
        } else if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
            inetIndex = inet6Index = originalIndex = 0;
        }

        iterator = resNew;
        while (iterator != NULL) {
            if (iterator->ai_family == AF_INET) {
                jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
                if (IS_NULL(iaObj)) {
                    ret = NULL;
                    goto cleanupAndReturn;
                }
                setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
                if ((*env)->ExceptionCheck(env))
                    goto cleanupAndReturn;
                setInetAddress_hostName(env, iaObj, host);
                if ((*env)->ExceptionCheck(env))
                    goto cleanupAndReturn;
                (*env)->SetObjectArrayElement(env, ret, (inetIndex | originalIndex), iaObj);
                inetIndex++;
            } else if (iterator->ai_family == AF_INET6) {
                jint scope = 0;
                jboolean ret1;
                jobject iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
                if (IS_NULL(iaObj)) {
                    ret = NULL;
                    goto cleanupAndReturn;
                }
                ret1 = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
                if (ret1 == JNI_FALSE) {
                    ret = NULL;
                    goto cleanupAndReturn;
                }
                scope = ((struct sockaddr_in6 *)iterator->ai_addr)->sin6_scope_id;
                if (scope != 0) { // zero is default value, no need to set
                    setInet6Address_scopeid(env, iaObj, scope);
                }
                setInetAddress_hostName(env, iaObj, host);
                if ((*env)->ExceptionCheck(env))
                    goto cleanupAndReturn;
                (*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
                inet6Index++;
            }
            if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
                originalIndex++;
                inetIndex = inet6Index = 0;
            }
            iterator = iterator->ai_next;
        }
    }
cleanupAndReturn:
    JNU_ReleaseStringPlatformChars(env, host, hostname);
    while (resNew != NULL) {
        last = resNew;
        resNew = resNew->ai_next;
        free(last);
    }
    if (res != NULL) {
        freeaddrinfo(res);
    }
    return ret;
}


http://www.niftyadmin.cn/n/5816282.html

相关文章

梯度下降方法

2.5 梯度下降方法介绍 学习目标 掌握梯度下降法的推导过程知道全梯度下降算法的原理知道随机梯度下降算法的原理知道随机平均梯度下降算法的原理知道小批量梯度下降算法的原理 上一节中给大家介绍了最基本的梯度下降法实现流程&#xff0c;本节我们将进一步介绍梯度下降法的详细…

Vue 环境配置与项目创建指南

1. 前置要求 在开始配置 Vue 开发环境之前&#xff0c;需要确保以下工具已安装&#xff1a; Node.js&#xff1a;Vue 的构建工具依赖 Node.js。 npm 或 yarn&#xff1a;Node.js 自带 npm 包管理工具&#xff0c;也可以选择安装 yarn。 安装 Node.js 前往 Node.js 官网 下…

来说数据库

什么是数据库&#xff1f; 是部署在操作系统上&#xff0c;把数据按一定的数据模型组织、永久存储&#xff0c;并可以被用户共享的软件系统。 其实数据库&#xff0c;可以理解为&#xff0c;把数据都存成文件&#xff0c;有很多的文件和很多的目录&#xff0c;不好管理&#xf…

五种数据库的安装

在线YUM仓库 打开MySQL官网&#xff08;MySQL&#xff09; 点击【Downloads】进入下载界面 点击【MySQL Community(GPL) Downloads】进入社区版下载界面 点击【MySQL Yum Repository】进入在线仓库安装界面 点击【Download】下载 点击【No,thanks,just start my download】直…

深入Android架构(从线程到AIDL)_16 应用Android的UI框架03

目录 6、 设计一个GameLoop类别 7、 只诞生一次GameLoop对象​编辑 6、 设计一个GameLoop类别 刚才的小线程&#xff0c;其实就扮演了游戏线程(Game thread)的角色&#xff0c;它负责控制游戏的循环。 // myView.java //…… public class myView extends View {//……….Ov…

js:事件流

事件流 事件流是指事件完整执行过程中的流动路径 一个事件流需要经过两个阶段&#xff1a;捕获阶段&#xff0c;冒泡阶段 捕获阶段是在dom树里获取目标元素的过程&#xff0c;从大到小 冒泡阶段是获取以后回到开始&#xff0c;从小到大&#xff0c;像冒泡一样 实际开发中大…

Bi-Encoder vs. Cross-Encoder

Bi-Encoder vs. Cross-Encoder Bi-Encoder 和 Cross-Encoder 是两种常见的模型架构&#xff0c;主要用于自然语言处理&#xff08;NLP&#xff09;中的文本匹配、问答、检索等任务。它们的主要区别在于如何处理输入文本以及计算相似度的方式。 1. Bi-Encoder&#xff08;双编…

近二百年历史传承,内藤酿造七醸烧用匠心打动中国市场

2025年1月5日&#xff0c;一场别开生面的蒸馏酒鉴赏会在上海隆重举行&#xff0c;标志着源自海外的蒸馏酒品牌——赏己七醸烧在中国市场的布局开启新的篇章。内藤酿造这家拥有近200年历史的综合性酒企&#xff0c;以其自主研发的御酵母、独特的七醸工艺、无与伦比的口感与中度白…