2、Internet地址(上)
连接到Internet的设备称为节点
计算机节点称为主机
每个节点或主机至少一个唯一的数来标识,这个节点称为Internet地址或者IP地址
目前大多数IP地址是四字节长,被称为IPv4地址
地址是16字节长,被称为IPv6
两者都是地址的有序序列,和数组一样
他们不是数,他们的顺序也不是具有任何可测或有用的意义
IPv4地址一般些微四个无符号字节,每个字节范围从0-255,最高字节在前
个节点之间用点作分隔符
如153.19.134.132
称为点分四段格式
IPv6地址通常写为冒号分割的8个区块
每个区块都是4个十六进制的数字
2400:cb00:2048:0001:0000:0000:6ca2:c665
前导为0需要写出:2400:cb00:2048:0001:0:0:6ca2:c665
两个冒号标识多个0区块
但是每个地址中双冒号至多出现一次
在IPv4和IPv6的混合网络中
IPv6的最后四个字节有时写为IPv4的点分四段地址
IP地址对于计算机来说很容易记忆
但是对人来说很难记忆
为了避免到处携带记IP地址的通讯录
Interne发明了域名系统
DNS将人们可以记忆的主机名与计算机记忆的IP地址关联在一起
服务器通常至少有一个主机名
客户端往往有一个主机名,但也可能没有
=人们通常使用的Internet标识一个主机名
=准备区分地址和主机名
有些机器有多个名
有时一个名对映射到多个IP地址,这时就要由DNS服务器负载随机选择一台机器来相应各个请求
这个特性在Web网站经常使用
负则将负载分摊到多个系统上
每台连接到Internet的计算机都应当能访问一个称为域名服务器的机器
它通常是一个运行特殊DNS软件的UNIX主机
这种软甲内链接不同主机名和IP地址之间的映射
大多数域名服务器只知道本地网络上的主机地址,以及其他网站中一些域名服务器的地址
如果客户端请求本地之外的一个机器地址,本地域名服务器就会询问远程位置的域名服务器,在将请求发给请求者
大多数情况下,可以使用主机名,而DNS处理向IP地址的转换
只要能连接到一个域名服务器,就不需要担心你的机器、本地域名服务器和Internet其余部分之间传递主机名和地址的有关细节
InetAddress类
java.net.InetAddress类是Java的IP地址的高层表示
大多数网络类都需要使用(Socket、ServerSocket、URL、DatagramSocket、DategramPacket等)
一般的来说,包括主机名和IP地址
创建新的InetAddress对象
InetAddress类没有公共构造函数
实际上InetAddress有一些静态的工厂方法
可以连接到DNS服务器来解析主机名
最长使用InetAddress.getName()
InetAddress address = InetAddress.getByName("www.baidu.com"); System.out.println(address);
同时可以本地ping一下
会与本地DNS服务器建立连接
来查找名字和数字地址(若查过,可能在缓存中进行查找)
DNS服务器找不到这个地址就会抛出一个UnknowHostException
还可以按照哦IP地址进行反向查找
可以向InetAddress.getByName()传入一个点分四段地址
InetAddress address = InetAddress.getByName("208.201.239.100"); System.out.println(address.getHostName());
如果查找的地址没有对应的主机名
getHostname()就会返回所提供的点分四段地址
有点域名会有多个地址
getHostName()返回哪一个地址是不缺定的
出于某种原因需要得到一个主机的所有地址可以使用getAllByName()返回一个数组
InetAddress[] addresses = InetAddress.getAllByName("www.oreilly.com"); for (InetAddress address : addresses){ System.out.println(address); }
getLocalHost()方法会为运行这个代码的主机返回一个InetAddress对象
InetAddress address = InetAddress.getLocalHost(); System.out.println(address);
会返回本地的地址主机名和点四分段地址
如果没有连接到Internet,系统没有固定的IP地址或域名,可能会看到localhost和127.0.0.1
如果知道一个数字地址
可以由这个地址创建一个InetAddress对象
不必使用InetAddress.getByAddress()与DNS交互
这个方法可以在不存在或者无法解析的主机创建地址:
第一个getByAddress()工厂方法用一个IP地址创建一个InetAddress对象
第二个InetAddress.getByAddress()方法使用一个IP地址和一个主机名创建InetAddress对象
byte [] address = {107,23, (byte) 216, (byte) 196}; InetAddress byAddress = InetAddress.getByAddress(address); InetAddress mrChengs = InetAddress.getByAddress("mrchengs.com", address);
这两个方法不能确保这个主机一定在,或者主机名能正确映射到IP地址
只有在传入的字节数组不合法时才会进行抛异常
缓存
由于DNS查找的开销可能很大
所以InetAddress类会缓存查找的结果
一旦得到一个给定的主机地址,就不会再次查找
即使为同一个主机创建新的InetAddress对象,也不会再次查找地址
只要在程序运行期间IP地址没有改变
负面结果:
有可能刚开始解析一个主机时失败
随后再次进行解析会成功
由于从远程DNS服务器发来的信息还在传输中
第一次尝试超时,然后这个地址到达服务器
所以下一次请求时可用,处于这个原因Java对不成功的DNS查询只缓存10秒
这些时间由
1、networkaddress.cache.ttl
2、networkaddress.cache.negative.ttl控制
第一个指定成功的DNS查询结果在缓存中保留的时间
第二个制定了不成功的查询在缓存中保存的时间
再次查询向的主机会返回相同的值,-1解释为永不过期
除了在InetAddress类中的本地缓存,本地主机、本地域名服务器和Internet上其他地方的DNS
服务器也会缓存何种查询结果
按IP地址进行查询
调用getName()并且提供一个IP地址串作为参数时
会为所有请求的IP地址创建一个InetAddress对象,而不检查DNS
说明:实际上会为不存在也无法连接的主机创建InetAddress对象
由包含IP地址的字符集来创建InetAddress对象时,这个对象的主机名楚世家为这个字符串
只有当请求主机名时(显示的通过getHostname()请求)
才会真正完成主机名的DNS查找
从点四分段法缺点域名地址
如果请求主机名并且完成了一个DNS查找
但是指定IP地址的主机无法找到
那么主机名会保持最初的点分四段字符串
不会抛异常
安全性问题
从主机名创建一个新的InetAddress对象被认为是一个不安全的操作
因为这需要一个DNS查找
在默认安全管理器控制下的不可信applet只允许获得它的初始化主机的IP地址
不允许不可信代码由其他任何其他主机名创建InetAddress对象
不论代码使用InetAddress.getByName()、InetAddress.getAllByName()方法等
不可信代码可以由字符串形式的ip地址构造InetAddress对象
但不会为这样的地址完成DNS查找
由于禁止与代码基之外的主机建立连接,不可信的代码不允许对第三方主机完成任意的DNS查找
任意的DNS查询会打开一个隐藏的通道
通过通道程序可以与第三方主机对话
获取方法
InetAddress包含四个获取方法:
getHostName()方法返回一个String,其中包含主机名义以及这个InetAddress对象表示的IP地址
如果这台计算机没有主机名或者安全管理器确定主机名,就会返回点分四段格式的数组IP地址
InetAddress localHost = InetAddress.getLocalHost(); String name = localHost.getHostName(); System.out.println(localHost); System.out.println(name);
getCanonicalHostname()方法也类似,在DNS联系方面更积极一点
getHostName()只是在不知道主机名时才会联系DNS
getCanonicalHostname()知道主机名也会联系DNS
InetAddress localHost = InetAddress.getLocalHost(); String name = localHost.getCanonicalHostName(); System.out.println(localHost); System.out.println(name);
如果开始只有一个点分四段IP地址而没有主机名
getCanonicalHostName()方法尤其重要
getHostAddress()方法返回一个 字符串
其中包括点分四段和的IP地址
InetAddress localHost = InetAddress.getLocalHost(); String name = localHost.getHostAddress(); System.out.println(name);
getAddress()以网络字节顺序将IP地址作为一个字节数组返回
InetAddress localHost = InetAddress.getLocalHost(); byte[] name = localHost.getAddress(); System.out.println(name[0]);
InetAddress byName = InetAddress.getByName("www.baidu.com"); System.out.println(byName);//www.baidu.com/115.239.211.112 System.out.println(byName.getHostName());//www.baidu.com System.out.println(byName.getAddress());//[B@14ae5a5 System.out.println(byName.getCanonicalHostName());//115.239.211.112 System.out.println(byName.getHostAddress());//115.239.211.112
确定IP地址是IPv4还是IPv6:
地址类型
Java提供了10个方法来测试InetAddress对象是否符合其中某个标准
1、
2、
3、
4、
5、
6、
7、
8、
9、
10、