dns解析系统整站源码-Java中InetAddress的使用(一):域名解析【享学Java】

程序员们,他们在想什么? 他们思考的永远是技术,他们敬佩的永远是技术。

目录

前言

Java有很好的网络编程模型/库,其中一个非常重要的API就是InetAddress。 java.net网络编程中很多类都会用到InetAddress,包括ServerSocket、Socket、DatagramSocket等。

如果要做网络编程,就必须有IP地址域名主机等要素。 一个InetAddress存储的是IP地址,还可能包含主机名,它提供了主机名-IP地址转换的方法(比域名的域名解析还简单,还不够好),我主要介绍它是为了看看如何玩。

关于常见网络概念,请提前做好功课:一文了解常见网络概念:域名、静态IP和动态IP、域名解析DNS、动态域名解析DDNS

文本

域名你并不陌生,IP地址你也不陌生,但域名解析对你来说可能有点陌生。 Java不希望用户了解太多DNS相关知识,因此使用InetAddress来完成域名与IP地址之间的转换。

Java域名解析

Java提供了InetAddress类(有Inet4Address和Inet6Address两种实现)dns解析系统整站源码,可以进行域名-IP的正向和反向解析。 InetAddress解析时一般会调用系统自带的DNS程序。

例如:Linux下默认使用哪个DNS进行解析,其规则由文件/etc/resolv.conf制定(该文件内容如上例内容)

dns解析系统整站源码_开源dns_源码站点

比如有些域名,不同地区有不同的IP; 因此,使用不同的DNS服务器进行解析,得到的IP一般是不同的。

简单来说:你所在的位置不同,解析的IP地址也不同。

Inet地址

IP地址是IP使用的32位(IPv4)或128位(IPv6)无符号数,是传输层协议TCP和UDP的基础。 InetAddress是Java对IP地址的封装。

java.net.IntAddress 类是 Java 的 IP 地址高级表示。 该类被大多数其他网络类使用,包括Socket、ServerSocket、URL、DatagramSocket、DatagramPacket等。InetAddress的实例对象包含IP地址,还可能包含主机名(如果使用主机名来获取InetAddress)实例,或者使用数字来构造它,并启用反向主机名解析)。 InetAddress 类提供将主机名解析为 IP 地址(或反之亦然)的方法。

InetAddress 使用本地机器配置(例如域名系统 DNS 和网络信息服务(Network Information Service,NIS))来解析域名。 本地需要向DNS服务器发送查询请求,然后服务器根据一系列操作返回对应的IP地址。 为了提高效率,本地通常会缓存一些主机名和IP地址的映射关系,这样访问同一个地址就不需要重复发送DNS请求。

该策略也用在 java.net.InetAddress 类中。 默认情况下,映射会缓存一段有限的时间,并且不成功的主机名解析的结果会缓存很短的时间(10 秒),以提高性能和准确性。

获取 InetAddress 实例的静态方法

InetAddress 不提供公共构造函数,但提供了 6 个静态方法供您构造实例:

public static InetAddress[] getAllByName(String host);
public static InetAddress getByName(String host);
public static InetAddress getByAddress(String host, byte[] addr);
public static InetAddress getByAddress(byte[] addr);
public static InetAddress getLoopbackAddress();
public static InetAddress getLocalHost();

下面给出解释。

注意:有些解析结果可能和我的不一样,因为即使是同一个域名,不同地方不同时间解析的IP也可能不同。

public static InetAddress[] getAllByName(String host):给定主机名,返回其IP地址数组,这些IP地址根据系统配置的DNS服务进行解析。 当然,host可以是主机名(域名),也可以是ip地址,下面是一个例子。

@Test
public void fun3() throws UnknownHostException {
    InetAddress[] inets = InetAddress.getAllByName("www.baidu.com");
    for (InetAddress inet : inets) {
    	// www.baidu.com/61.135.169.125
    	// www.baidu.com/61.135.169.121
        System.out.println(inet);
    }
}

public static InetAddress getByName(String host):其原理就是上面的方法 -> InetAddress.getAllByName(host)[0] 就是第一个值

@Test
public void fun2() throws UnknownHostException {
    // 网络域名
    InetAddress inet = InetAddress.getByName("www.baidu.com");
    System.out.println("域名:" + inet.getHostName()); // 域名:www.baidu.com
    System.out.println("IP地址:" + inet.getHostAddress()); // IP地址:61.135.169.125
    // 本地域名(本机)
    inet = InetAddress.getByName("localhost");
    System.out.println("域名:" + inet.getHostName()); // 域名:localhost
    System.out.println("IP地址:" + inet.getHostAddress()); // IP地址:127.0.0.1
    // 不存在的域名 抛出异常:java.net.UnknownHostException: aaaaaa.com
    // tips:abc.com这种域名是存在的哟
    inet = InetAddress.getByName("aaaaaa.com");
    System.out.println("域名:" + inet.getHostName());
    System.out.println("IP地址:" + inet.getHostAddress());
}

对于这部分的域名解析,有以下注意事项:

不能通过协议添加域名。 如果这样写,就会抛出UnknownHostException。 对于外网的域名解析,每个人解析的地址可能会不一样。比如我这里解析得到的地址是61.135.169.125,因为我在北京,所以得到了北京的IP地址

另外dns解析系统整站源码,为了方便大家看到windows中DNS缓存的效果,可以使用这两个命令来查看:

上面两个方法也叫: 创建一个带有域名的InetAddress对象。 如果想通过这种方式获取IP,就必须经过DNS服务解析~

但请注意:如果您的主机传入ip地址,则不会被DNS解析

public static InetAddress getByAddress(String host, byte[] addr):根据提供的主机名和IP地址创建InetAddress

@Test
public void fun0() throws UnknownHostException {
    // 同时指定域名 和 ip地址,那就是自己建立了对应关系喽
    InetAddress inet = InetAddress.getByAddress("www.baidu.com", new byte[]{61, (byte) 135, (byte) 169, 125});
    System.out.println("域名:" + inet.getHostName()); // 域名:www.baidu.com
    System.out.println("IP地址:" + inet.getHostAddress()); // IP地址:61.135.169.125
}

public static InetAddress getByAddress(byte[] addr):返回给定原始 IP 地址的 InetAddress 对象。

@Test
public void fun1() throws UnknownHostException {
    InetAddress inet = InetAddress.getByAddress(new byte[]{61, (byte) 135, (byte) 169, 125});
    // 若你要获取主机名,就尝试通过网络帮你找,所以一般比较耗时,不建议使用。  找不到就原样输出
    // System.out.println("域名:" + inet.getHostName()); // 域名:61.135.169.125
    System.out.println("IP地址:" + inet.getHostAddress()); // IP地址:61.135.169.125
}

以上两种方法:通过IP构造一个InetAddress对象,这样当你获取到它的IP地址时,就不再经过DNS解析了。

public static InetAddress getLoopbackAddress():1.7中的新方法。获取环回地址

@Test
public void fun4() {
    InetAddress inet = InetAddress.getLoopbackAddress();
    System.out.println("域名:" + inet.getHostName()); // 域名:localhost
    System.out.println("IP地址:" + inet.getHostAddress()); // IP地址:127.0.0.1
}

public static InetAddress getLocalHost():获取本机的地址(该方法需要特别注意,Linux下不要直接使用)

@Test
public void fun5() throws UnknownHostException {
    InetAddress inet = InetAddress.getLocalHost();
    System.out.println("域名:" + inet.getHostName()); // LP-BJ4556
    System.out.println("IP地址:" + inet.getHostAddress()); // IP地址:2.0.0.137
}

为什么地址是2.0.0.137? 请参考下面的截图:

源码站点_开源dns_dns解析系统整站源码

因为我打开了VPN,所以它获取了VPN网络接口的IP地址。 但如果我关闭VPN,则会返回正常的192.168.199.175。 另外,该方法在Linux下使用时几乎都会返回127.0.0.1,因为Linux下它只读取hosts文件的内容,而Linux下的hosts文件一般包含以下内容:

# 这里你若配置为127.0.0.2,那么getLocalHost()就返回127.0.0.2
127.0.0.1   localhost 
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.102.1.153 l-xxx.syc.prod.ali.qr

综上所述,在生产中,不要直接使用getLocalHost()方法来获取本地IP。 不要直接使用getLocalHost()方法获取本地IP。 不要直接使用getLocalHost()方法获取本地IP。

域名只绑定一个地址的小问题解答

最后备注添加了一位小伙伴问我一个小问题,示例代码如下:

public static void main(String[] args) throws UnknownHostException {
    InetAddress[] addresses = InetAddress.getAllByName("xxx.com -> 公司的内网域名");
    for (InetAddress address : addresses) {
        System.out.println(address.getHostAddress());
    }
}

他发现无论运行多少次,返回的总是一个地址值,他不禁要问,难道一个内网域名只能绑定一台机器吗? ? ?

其实并不是。 一般来说,微服务系统中的内网域名一般都会解析到你公司的Nginx机器上,Nginx负责后端实例的负载均衡(不信你试试换几个内网域名)同一类别的。你会发现解析出来的ip地址都是一样的->就是你NG机器的地址)。

总结

本文重点介绍Java中InetAddress的使用。 它是IP地址的高级封装,是网络编程中不可或缺的API。 虽然它有两个子类,但实际上我们只会使用InetAddress。

本文最后留下一个小问题:生产中不建议使用getLocalHost()直接获取机器的IP地址,而且这是一个比较高频的需求。 怎么解决呢? 这个问题留待二方来回答吧~

关注A兄弟 作者A (YourBatman)

个人网站

电子邮件

yourbatman@qq.com

微信

fsx641385712

活跃平台

没有公开

BAT的乌托邦(ID:BAT-utopia)

知识星球

BAT的乌托邦