本站首页    管理页面    写新日志    退出


«September 2025»
123456
78910111213
14151617181920
21222324252627
282930


公告

戒除浮躁,读好书,交益友


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:邢红瑞的blog
日志总数:523
评论数量:1142
留言数量:0
访问次数:9703591
建立时间:2004年12月20日




[jvm]java的DNS查找的实现
原创空间,  软件技术,  电脑与网络

邢红瑞 发表于 2005/1/11 10:41:38

 使用java的getByName函数。public static InetAddress getByName(String host)                             throws UnknownHostException在给定主机名的情况下确定主机的 IP 地址。 主机名可以是机器名(如 "java.sun.com"),也可以是其 IP 地址的文本表示形式。如果提供字面值 IP 地址,则仅检查地址格式的有效性。 对于以字面值 IPv6 地址指定的 host,在 RFC 2732 中定义的形式或在 RFC 2373 中定义的字面值 IPv6 地址格式都可以接受。IPv6 范围地址也受支持。有关 IPv6 范围地址的描述,请参见这里。 如果主机为 null,则返回表示回送接口地址的 InetAddress。请参阅 RFC 3330 的第 2 节和 RFC 2373 的第 2.5.3 节。 参数:host - 指定的主机,或 null。 返回:给定主机名的 IP 地址。 抛出: UnknownHostException - 如果找不到 host 的 IP 地址,或者 scope_id 是为全局 IPv6 地址指定的。 SecurityException - 如果安全管理器存在并且其 checkConnect 方法不允许进行该操作 -------------------------------------------------------------------------------- getAllByNamepublic static InetAddress[] getAllByName(String host)                                  throws UnknownHostException在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。 主机名可以是机器名(如 "java.sun.com"),也可以是其 IP 地址的文本表示形式。如果提供字面值 IP 地址,则仅检查地址格式的有效性。 对于以字面值 IPv6 地址 指定的 host,在 RFC 2732 中定义的形式或在 RFC 2373 中定义的字面值 IPv6 地址格式都可以接受。字面值 IPv6 地址还可以通过追加范围时区标识符或 scope_id 来限定。scope_id 的语法和用法在这里描述。 如果主机为 null,则返回表示回送接口地址的 InetAddress。请参阅 RFC 3330 的第 2 节和 RFC 2373 的第 2.5.3 节。 如果有安全管理器,并且 host 非 null,host.length() 不等于零,则使用主机名和 -1 作为参数调用安全管理器的 checkConnect 方法,来查看是否允许该操作。 参数:host - 主机名,或 null。 返回:给定主机名的所有 IP 地址所组成的数组。 抛出: UnknownHostException - 如果找不到 host 的 IP 地址,或者 scope_id 是为全局 IPv6 地址指定的。 SecurityException - 如果安全管理器存在并且其 checkConnect 方法不允许进行该操作。另请参见:SecurityManager.checkConnect(java.lang.String, int) 例如  查找sohu的IP地址, try {            InetAddress remosthost = InetAddress.getByName("www.sohu.com");            System.out.println("remosthost:   " + remosthost.getHostAddress());            System.out.println("remosthost:   " + remosthost.getHostName());         } catch (UnknownHostException uhe) {            System.err.println("Localhost   not   seeable.   Something   is   odd.   ");        }其实sohu不会是一个ip,它是一个IP组  try {            InetAddress[] remosthost = InetAddress.getAllByName("www.sohu.com");            for (int i = 0; i < remosthost.length; i++) {                System.out.println("remosthost:   " + remosthost[i].getHostAddress());                System.out.println("remosthost:   " + remosthost[i].getHostName());            }         } catch (UnknownHostException uhe) {            System.err.println("Localhost   not   seeable.   Something   is   odd.   ");        }sun的jdk源码,只看InetAddress的IPv4实现,Inet4AddressImpl实现了InetAddressImpl,而InetAddressImpl定义了 byte[][]        lookupAllHostAddr(String hostname) throws UnknownHostException;就是这个最终实现。打开InetAddress, public static InetAddress getByName(String host) throws UnknownHostException { return InetAddress.getAllByName(host)[0];    }getByName调用了getAllByName  /**     * Given the name of a host, returns an array of its IP addresses,     * based on the configured name service on the system.     *      * <p> The host name can either be a machine name, such as     * "<code>java.sun.com</code>", or a textual representation of its IP     * address. If a literal IP address is supplied, only the     * validity of the address format is checked.     *     * <p> For <code>host</code> specified in <i>literal IPv6 address</i>,     * either the form defined in RFC 2732 or the literal IPv6 address     * format defined in RFC 2373 is accepted. A literal IPv6 address may     * also be qualified by appending a scoped zone identifier or scope_id.     * The syntax and usage of scope_ids is described      * <a href="Inet6Address.html#scoped">here</a>.     * <p> If the host is <tt>null</tt> then an <tt>InetAddress</tt>     * representing an address of the loopback interface is returned.     * See <a href="RFC&nbsp;3330http://www.ietf.org/rfc/rfc3330.txt">RFC&nbsp;3330</a>     * section&nbsp;2 and <a href="RFC&nbsp;2373http://www.ietf.org/rfc/rfc2373.txt">RFC&nbsp;2373</a>     * section&nbsp;2.5.3. </p>     *     * <p> If there is a security manager and <code>host</code> is not      * null and <code>host.length() </code> is not equal to zero, the     * security manager's     * <code>checkConnect</code> method is called     * with the hostname and <code>-1</code>      * as its arguments to see if the operation is allowed.     *     * @param      host   the name of the host, or <code>null</code>.     * @return     an array of all the IP addresses for a given host name.     *      * @exception  UnknownHostException  if no IP address for the     *               <code>host</code> could be found, or if a scope_id was specified     *       for a global IPv6 address.     * @exception  SecurityException  if a security manager exists and its       *               <code>checkConnect</code> method doesn't allow the operation.     *      * @see SecurityManager#checkConnect     */    public static InetAddress[] getAllByName(String host) throws UnknownHostException {  if (host == null || host.length() == 0) {     InetAddress[] ret = new InetAddress[1];     ret[0] = impl.loopbackAddress();     return ret; }  boolean ipv6Expected = false; if (host.charAt(0) == '[') {     // This is supposed to be an IPv6 litteral     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 address, but it's not!  throw new UnknownHostException(host);     } }  // if host is an IP address, we won't do further lookup if (Character.digit(host.charAt(0), 16) != -1      || (host.charAt(0) == ':')) {     byte[] addr = null;     int numericZone = -1;     String ifname = null;     // see if it is IPv4 address     addr = IPAddressUtil.textToNumericFormatV4(host);     if (addr == null) {  // see if it is IPv6 address  // Check if a numeric or string zone id is present  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);      }  }   addr = IPAddressUtil.textToNumericFormatV6(host);     } else if (ipv6Expected) {  // Means an IPv4 litteral between brackets!  throw new UnknownHostException("["+host+"]");     }     InetAddress[] ret = new InetAddress[1];     if(addr != null) {  if (addr.length == Inet4Address.INADDRSZ) {      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 Litteral, but got something else  throw new UnknownHostException("["+host+"]");     } return getAllByName0(host);    }getAllByName调用了getAllByName0 /**     * package private so SocketPermission can call it     */    static InetAddress[] getAllByName0 (String host, boolean check) throws UnknownHostException  { /* If it gets here it is presumed to be a hostname */ /* Cache.get can return: null, unknownAddress, or InetAddress[] */        Object obj = null; Object objcopy = null;  /* make sure the connection to the host is allowed, before we  * give out a hostname  */ if (check) {     SecurityManager security = System.getSecurityManager();     if (security != null) {  security.checkConnect(host, -1);     } }  obj = getCachedAddress(host);  /* If no entry in cache, then do the host lookup */ if (obj == null) {     try {         obj = getAddressFromNameService(host);     } catch (UnknownHostException uhe) {  throw new UnknownHostException(host + ": " + uhe.getMessage());     } }  if (obj == unknown_array)      throw new UnknownHostException(host);  /* Make a copy of the InetAddress array */ objcopy = ((InetAddress [])obj).clone();  return (InetAddress [])objcopy;    }getAllByName0调用了getCachedAddress /*     * Lookup hostname in cache (positive & negative cache). If     * found return address, null if not found.     */    private static Object getCachedAddress(String hostname) {        hostname = hostname.toLowerCase();  // search both positive & negative caches  synchronized (addressCache) {     CacheEntry entry;      cacheInitIfNeeded();      entry = (CacheEntry)addressCache.get(hostname);     if (entry == null) {  entry = (CacheEntry)negativeCache.get(hostname);     }      if (entry != null) {         return entry.address;     }  }  // not found return null;    }     static {   // create the impl impl = (new InetAddressImplFactory()).create();  // get name service if provided and requested String provider = null;; String propPrefix = "sun.net.spi.nameservice.provider."; int n = 1;     while (nameService == null) {  provider       = (String)AccessController.doPrivileged(   new GetPropertyAction(propPrefix+n, "default"));  n++;  if (provider.equals("default")) {      // initialize the default name service      nameService = new NameService() {   public byte[][] lookupAllHostAddr(String host)        throws UnknownHostException {       return impl.lookupAllHostAddr(host);   }   public String getHostByAddr(byte[] addr)        throws UnknownHostException {       return impl.getHostByAddr(addr);   }      };      break;  }   final String providerName = provider;   try {      java.security.AccessController.doPrivileged(   new java.security.PrivilegedExceptionAction() {       public Object run() {    Iterator itr            = Service.providers(NameServiceDescriptor.class);    while (itr.hasNext()) {            NameServiceDescriptor nsd      = (NameServiceDescriptor)itr.next();            if (providerName.            equalsIgnoreCase(nsd.getType()+","                +nsd.getProviderName())) {     try {                 nameService = nsd.createNameService();                 break;     } catch (Exception e) {         e.printStackTrace();                 System.err.println(      "Cannot create name service:"              +providerName+": " + e);     }            }    } /* while */           return null;   }      });  } catch (java.security.PrivilegedActionException e) {  }      }    }getCachedAddress调用了lookupAllHostAddr,lookupAllHostAddr是个native方法,Inet4AddressImpl.c文件,调用了gethostbyname windowsAPI/* * Find an internet address for a given hostname.  Not this this * code only works for addresses of type INET. The translation * of %d.%d.%d.%d to an address (int) occurs in java now, so the * String "host" shouldn't be a %d.%d.%d.%d string. The only  * exception should be when any of the %d are out of range and * we fallback to a lookup. * * Class:     java_net_Inet4AddressImpl * Method:    lookupAllHostAddr * Signature: (Ljava/lang/String;)[[B * * This is almost shared code */ JNIEXPORT jobjectArray JNICALL Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,       jstring host) {    const char *hostname;    struct hostent *hp;    unsigned int addr[4];     jobjectArray ret = NULL;    jclass byteArrayCls;     if (IS_NULL(host)) { JNU_ThrowNullPointerException(env, "host argument"); return NULL;    }    hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);    CHECK_NULL_RETURN(hostname, NULL);     /*     * The NT/2000 resolver tolerates a space in front of localhost. This     * is not consistent with other implementations of gethostbyname.     * In addition we must do a white space check on Solaris to avoid a     * bug whereby 0.0.0.0 is returned if any host name has a white space.     */    if (isspace(hostname[0])) { JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", hostname); goto cleanupAndReturn;    }     /*     * If the format is x.x.x.x then don't use gethostbyname as Windows     * is unable to handle octets which are out of range.     */    if (isDottedIPAddress(hostname, &addr[0])) { unsigned int address; jbyteArray barray; jobjectArray oarray;   /*   * Are any of the octets out of range?  */ if (addr[0] > 255 || addr[1] > 255 || addr[2] > 255 || addr[3] > 255) {     JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", hostname);     goto cleanupAndReturn; }  /*  * Return an byte array with the populated address.  */ address = (addr[3]<<24) & 0xff000000; address |= (addr[2]<<16) & 0xff0000; address |= (addr[1]<<8) & 0xff00; address |= addr[0];  byteArrayCls = (*env)->FindClass(env, "[B"); if (byteArrayCls == NULL) {     goto cleanupAndReturn; }  barray = (*env)->NewByteArray(env, 4); oarray = (*env)->NewObjectArray(env, 1, byteArrayCls, NULL);  if (barray == NULL || oarray == NULL) {     /* pending exception */     goto cleanupAndReturn; } (*env)->SetByteArrayRegion(env, barray, 0, 4, (jbyte *)&address); (*env)->SetObjectArrayElement(env, oarray, 0, barray);  JNU_ReleaseStringPlatformChars(env, host, hostname); return oarray;     }     /*     * Perform the lookup     */    if ((hp = gethostbyname((char*)hostname)) != NULL) { struct in_addr **addrp = (struct in_addr **) hp->h_addr_list; int len = sizeof(struct in_addr); int i = 0;  while (*addrp != (struct in_addr *) 0) {     i++;     addrp++; }  byteArrayCls = (*env)->FindClass(env, "[B"); if (byteArrayCls == NULL) {     goto cleanupAndReturn; }         ret = (*env)->NewObjectArray(env, i, byteArrayCls, NULL); if (IS_NULL(ret)) {     goto cleanupAndReturn; }  addrp = (struct in_addr **) hp->h_addr_list; i = 0; while (*addrp != (struct in_addr *) 0) {     jbyteArray barray = (*env)->NewByteArray(env, len);     if (IS_NULL(barray)) {  JNU_ThrowOutOfMemoryError(env, "lookupAllHostAddr");  ret = NULL;  goto cleanupAndReturn;     }     (*env)->SetByteArrayRegion(env, barray, 0, len, (jbyte *)(*addrp));     (*env)->SetObjectArrayElement(env, ret, i, barray);     addrp++;     i++; }    } else {        JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", hostname);    } cleanupAndReturn:    JNU_ReleaseStringPlatformChars(env, host, hostname);    return ret;}


阅读全文(4814) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.043 second(s), page refreshed 144772994 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号