Java篇:Java网络编程(二)网络地址及端口
2 网络地址及端口
InetAddress类表示Internet协议(IP)地址,其包含两个由final修饰的子类Inet4Address和Inet6Address分别表示IPv4地址和IPv6地址。
目前的全球因特网所采用的协议簇是TCP/IP协议族,IP是TCP/IP协议族中网络层的协议,是TCP/IP协议族的核心协议。目前IP协议的版本号是4(简称IPv4),发展至今已经使用了30多年。IPv4的地址位数为32位,也就是最多有2的32次方的电脑可以联到Internet上,近十年来由于互联网的蓬勃发展,IP地址的发放愈趋严格,各项资料显示全球IPv4地址可能在2005至2008年间全部发完。
而IPv6是下一版本地互联网协议,它地提出最初是因为随着互联网地迅速发展,IPv4定义的有限地址将被耗尽,地址空间的不足必将妨碍互联网的近一步发展。
2.1.1 InetAddress
InetAddress的构造方法并不可直接访问,而是通过提供的6个静态方法返回InetAddress实例。不知道是否因为现在仍是以IPv4地址为主,以下静态方法,默认优先返回的是IPv4地址。
InetAddress对域名进行解析是使用本地机器配置或者网络命名服务(如域名系统(Domain Name System,DNS)和网络信息服务(Network Information Service,NIS))来实现。
INETADDRESS 构造方法:通过静态方法返回 | |
---|---|
static InetAddress[] getAllByName(String host) | 给定主机的名称,根据系统上配置的名称服务返回其IP地址数组。 |
static InetAddress getByAddress(byte[] addr) | 给出原始IP地址的 InetAddress对象。 |
static InetAddress getByAddress(String host, byte[] addr) | 根据提供的主机名和IP地址创建InetAddress。 |
static InetAddress getByName(String host) | 确定主机名称的IP地址。 |
static InetAddress getLocalHost() | 返回本地主机的地址。 |
static InetAddress getLoopbackAddress() | 返回回送地址。 |
InetAddress类提供了对IP地址进行判断的一些方法以及返回IP地址信息的方法。
INETADDRESS 其他方法 | |
---|---|
boolean equals(Object obj) | 将此对象与指定对象进行比较。 |
boolean isAnyLocalAddress() | 检查通配符地址中的InetAddress的实用程序。 |
boolean isLinkLocalAddress() | 检查InetAddress是否是链接本地地址的实用程序。 |
boolean isLoopbackAddress() | 检查InetAddress是否是一个环回地址的实用程序。 |
boolean isMCGlobal() | 检查多播地址是否具有全局范围的实用程序。 |
boolean isMCLinkLocal() | 检查组播地址是否具有链路范围的实用程序。 |
boolean isMCNodeLocal() | 检查多播地址是否具有节点范围的实用程序。 |
boolean isMCOrgLocal() | 检查组播地址是否具有组织范围的实用程序。 |
boolean isMCSiteLocal() | 检查多播地址是否具有站点范围的实用程序。 |
boolean isMulticastAddress() | 检查InetAddress是否是IP组播地址的实用程序。 |
boolean isReachable(int timeout) | 测试该地址是否可达。 |
boolean isReachable(NetworkInterface netif, int ttl, int timeout) | 测试该地址是否可达。 |
boolean isSiteLocalAddress() | 检查InetAddress是否是站点本地地址的实用程序。 |
byte[] getAddress() | 返回此 InetAddress对象的原始IP地址。 |
String getCanonicalHostName() | 获取此IP地址的完全限定域名。 |
String getHostAddress() | 返回文本显示中的IP地址字符串。 |
String getHostName() | 获取此IP地址的主机名。 |
String toString() | 将此IP地址转换为 String 。 |
int hashCode() | 返回此IP地址的哈希码。 |
2.1.2 Inet4Address
Inet4Address作为InetAddress的直接子类,并没有重写构造方法。其支持的方法也与InetAddress相似。
INET4ADDRESS 方法 | |
---|---|
boolean equals(Object obj) | 将此对象与指定对象进行比较。 |
byte[] getAddress() | 返回此 InetAddress对象的原始IP地址。 |
以文本表示形式返回IP地址字符串。 | |
int hashCode() | 返回此IP地址的哈希码。 |
boolean isAnyLocalAddress() | 检查通配符地址中的InetAddress的实用程序。 |
boolean isLinkLocalAddress() | 检查InetAddress是否是链接本地地址的实用程序。 |
boolean isLoopbackAddress() | 检查InetAddress是否是一个环回地址的实用程序。 |
boolean isMCGlobal() | 检查多播地址是否具有全局范围的实用程序。 |
boolean isMCLinkLocal() | 检查组播地址是否具有链路范围的实用程序。 |
boolean isMCNodeLocal() | 检查多播地址是否具有节点范围的实用程序。 |
boolean isMCOrgLocal() | 检查组播地址是否具有组织范围的实用程序。 |
boolean isMCSiteLocal() | 检查多播地址是否具有站点范围的实用程序。 |
boolean isMulticastAddress() | 检查InetAddress是否是IP组播地址的实用程序。 |
boolean isSiteLocalAddress() | 检查InetAddress是否是站点本地地址的实用程序。 |
2.1.3 Inet6Address
同样作为作为InetAddress的直接子类,Inet6Address却有些不同。构造Inet6Address实例的方法必须通过传入host、addr、scope_id/NetworkInterface nif来返回。
INET6ADDRESS 构造方法:通过静态方法返回 | |
---|---|
static Inet6Address getByAddress(String host, byte[] addr, int scope_id) | 在的确切方式创建Inet6Address, InetAddress.getByAddress(String,byte[])不同之处在于将IPv6 scope_id设置为给定数值。 |
static Inet6Address getByAddress(String host, byte[] addr, NetworkInterface nif) | 在的确切方式创建Inet6Address, InetAddress.getByAddress(String,byte[])不同之处在于将IPv6 scope_id设置为对应于在指定的地址类型的给定接口的值 addr 。 |
INET6ADDRESS 其他方法 | |
---|---|
boolean equals(Object obj) | 将此对象与指定对象进行比较。 |
byte[] getAddress() | 返回此 InetAddress对象的原始IP地址。 |
NetworkInterface getScopedInterface() | 如果此实例是使用范围界面创建的,则返回范围界面。 |
String getHostAddress() | 返回文本显示中的IP地址字符串。 |
int getScopeId() | 如果此实例与接口相关联,则返回数字scopeId。 |
boolean isAnyLocalAddress() | 检查通配符地址中的InetAddress的实用程序。 |
boolean isIPv4CompatibleAddress() | 检查InetAddress是否与IPv4兼容的IPv6地址的实用程序。 |
boolean isLinkLocalAddress() | 检查InetAddress是否是链接本地地址的实用程序。 |
boolean isLoopbackAddress() | 检查InetAddress是否是一个环回地址的实用程序。 |
boolean isMCGlobal() | 检查多播地址是否具有全局范围的实用程序。 |
boolean isMCLinkLocal() | 检查组播地址是否具有链路范围的实用程序。 |
boolean isMCNodeLocal() | 检查多播地址是否具有节点范围的实用程序。 |
boolean isMCOrgLocal() | 检查组播地址是否具有组织范围的实用程序。 |
boolean isMCSiteLocal() | 检查多播地址是否具有站点范围的实用程序。 |
boolean isMulticastAddress() | 检查InetAddress是否是IP组播地址的实用程序。 |
boolean isSiteLocalAddress() | 检查InetAddress是否是站点本地地址的实用程序。 |
int hashCode() | 返回此IP地址的哈希码。 |
2.1.4 简单应用
static void test1(){ try { /* ********查看cdn中百度域名对应的IP************************* */ String hostname = "www.baidu.com"; System.out.println("域名:"+hostname); InetAddress[] addresses = InetAddress.getAllByName(hostname); int[] countIp = {0,0}; for(int i=0;i<addresses.length;i++){ //统计IPv4地址的数量 if (addresses[i] instanceof Inet4Address){ countIp[0]++; System.out.println(String.format("IPv4地址%d:%s",countIp[0],addresses[i].getHostAddress())); } // 统计IPv6地址的数据量 else if (addresses[i] instanceof Inet6Address){ countIp[1]++; System.out.println(String.format("IPv6地址%d:%s",countIp[1],addresses[i].getHostAddress())); } } System.out.println(String.format("本机IPv4地址数量:%d,IPv6地址数量:%d\n\n",countIp[0],countIp[1])); /* **********************查看本机地址*************************************** */ // 获取本机IP地址 InetAddress localInet = InetAddress.getLocalHost(); //获取本机名称 String localHostname = localInet.getHostName(); System.out.println("本机机名:"+localHostname); //根据本机名称获取本机全部ip(一般会包含IPv4,Ipv6的号码) InetAddress[] localAdresses = InetAddress.getAllByName(localHostname); countIp[0]=0; countIp[1]=0; for(int i=0;i<localAdresses.length;i++){ //统计IPv4地址的数量 if (localAdresses[i] instanceof Inet4Address){ countIp[0]++; System.out.println(String.format("IPv4地址%d:%s",countIp[0],localAdresses[i].getHostAddress())); } // 统计IPv6地址的数据量 else if (localAdresses[i] instanceof Inet6Address){ countIp[1]++; System.out.println(String.format("IPv6地址%d:%s",countIp[1],localAdresses[i].getHostAddress())); } } System.out.println(String.format("本机IPv4地址数量:%d,IPv6地址数量:%d\n\n",countIp[0],countIp[1])); /* ***********************Inet6Address************************ */ /* IPv6测试的样例好像只能找到自己本机的地址 localAdresses*/ int inet6AddressScopeId=0; String inet6AddressHostname=""; byte[] inet6AddressS={0}; for(int i=0;i<localAdresses.length;i++){ // 获取IPv6地址 if (localAdresses[i] instanceof Inet6Address){ inet6AddressScopeId = ((Inet6Address) localAdresses[i]).getScopeId(); inet6AddressHostname = localAdresses[i].getHostName(); inet6AddressS = localAdresses[i].getAddress(); break; } } Inet6Address inet6Address = Inet6Address.getByAddress(inet6AddressHostname,inet6AddressS,inet6AddressScopeId); System.out.println(String.format("IPv6地址:%s",inet6Address.getHostAddress())); System.out.println(inet6Address.isIPv4CompatibleAddress()); } catch (UnknownHostException e) { e.printStackTrace(); } }
2.2 网络地址+端口
2.2.1 SocketAddress
这个类代表一个没有协议附件的Socket地址。 作为一个抽象类,它的意思是使用特定的,依赖于协议的实现进行子类化。
它提供了用于绑定,连接或返回值的套接字所使用的不可变对象。
2.2.2 InetSocketAddress
2.2.2.1 InetSocketAddress
该类实现IP套接字地址(IP地址+端口号)它也可以是一对(主机名+端口号),在这种情况下将尝试解析主机名。 如果解决方案失败,那么该地址被认为是未解决的,但在某些情况下仍可以使用,例如通过代理连接。
它提供了用于绑定,连接或返回值的套接字所使用的不可变对象。
通配符是一个特殊的本地IP地址。 通常意味着“任何”,只能用于bind操作。
构造方法 | |
---|---|
InetSocketAddress(InetAddress addr, int port) | 从IP地址和端口号创建套接字地址。 |
InetSocketAddress(int port) | 创建一个套接字地址,其中IP地址为通配符地址,端口号为指定值。 |
InetSocketAddress(String hostname, int port) | 从主机名和端口号创建套接字地址。 |
MODIFIER AND TYPE | METHOD AND DESCRIPTION |
---|---|
从主机名和端口号创建未解析的套接字地址。 | |
获得 InetAddress 。 | |
boolean equals(Object obj) | 将此对象与指定对象进行比较。 |
获得 hostname 。 | |
如果没有主机名(使用文字创建),则返回主机名或地址的String形式。 | |
int getPort() | 获取端口号。 |
boolean isUnresolved() | 检查地址是否已解析成功。 |
int hashCode() | 返回该套接字地址的哈希码。 |
构造此InetSocketAddress的字符串表示形式。 |
2.2.2.2 代码应用
static void test2(){ InetSocketAddress inetSocketAddress = new InetSocketAddress(9999); System.out.println(inetSocketAddress); System.out.println(inetSocketAddress.isUnresolved()+"\n\n"); try { InetAddress localInet = InetAddress.getLocalHost(); inetSocketAddress = new InetSocketAddress(localInet,9999); System.out.println(inetSocketAddress); System.out.println(inetSocketAddress.isUnresolved()+"\n\n"); inetSocketAddress = InetSocketAddress.createUnresolved(localInet.getHostName(),9999); System.out.println(inetSocketAddress); System.out.println(inetSocketAddress.isUnresolved()+"\n\n"); } catch (UnknownHostException e) { e.printStackTrace(); } }
2.2.3 InterfaceAddress
此类表示网络接口地址。 简而言之,当地址是IPv4地址时,它是一个IP地址,一个子网掩码和一个广播地址。 在IPv6地址的情况下,IP地址和网络前缀长度。
InterfaceAddress似乎并没有提供构造方法,一般来说应该是通过其他类来进行构建,比如NetworkInterface。
INTERFACEADDRESS包含的方法 | |
---|---|
InetAddress getAddress() | 返回此地址的 InetAddress 。 |
InetAddress getBroadcast() | InetAddress的广播地址返回InetAddress。 |
short getNetworkPrefixLength() | 返回此地址的网络前缀长度。 |
boolean equals(Object obj) | 将此对象与指定对象进行比较。 |
int hashCode() | 返回此接口地址的哈希码。 |
String toString() | 将此接口地址转换为 String 。 |
2.2.4 NetworkInterface
2.2.4.1 NetworkInterface
此类表示由名称组成的网络接口和分配给此接口的IP地址列表。 用于标识组播组所在的本地接口。 接口通常由诸如“le0”的名称所知。
NETWORKINTERFACE包含的方法 | |
---|---|
static Enumeration<NetworkInterface> getNetworkInterfaces() | 返回本机上的所有接口。 |
static NetworkInterface getByIndex(int index) | 获取一个网络接口给它的索引。 |
static NetworkInterface getByInetAddress(InetAddress addr) | 搜索具有绑定到指定的Internet协议(IP)地址的网络接口的便利方法。 |
static NetworkInterface getByName(String name) | 搜索具有指定名称的网络接口。 |
String getDisplayName() | 获取此网络接口的显示名称。 |
byte[] getHardwareAddress() | 返回接口的硬件地址(通常为MAC),如果它有一个,如果可以访问给定当前权限。 |
int getIndex() | 返回此网络接口的索引。 |
Enumeration<InetAddress> getInetAddresses() | 使用绑定到此网络接口的InetAddresses全部或一部分子枚举的枚举方法。 |
List<InterfaceAddress> getInterfaceAddresses() | 获取此网络接口的 InterfaceAddresses的全部或部分的列表。 |
int getMTU() | 返回此接口的最大传输单元(MTU)。 |
String getName() | 获取此网络接口的名称。 |
NetworkInterface getParent() | 返回此接口的父NetworkInterface;如果这是一个子接口,或 null如果它是一个物理(非虚拟的)接口或没有父。 |
Enumeration<NetworkInterface> getSubInterfaces() | 获取连接到此网络接口的所有子接口(也称为虚拟接口)的枚举。 |
boolean isLoopback() | 返回网络接口是否是环回接口。 |
boolean isPointToPoint() | 返回网络接口是否是点对点接口。 |
boolean isUp() | 返回网络接口是否启动并运行。 |
boolean isVirtual() | 返回此接口是否为虚拟接口(也称为子接口)。 |
boolean supportsMulticast() | 返回网络接口是否支持多播。 |
boolean equals(Object obj) | 将此对象与指定对象进行比较。 |
String toString() | 返回对象的字符串表示形式。 |
int hashCode() | 返回对象的哈希码值。 |
2.2.4.2 简单应用
-
NetworkInterface的构造方法,通过getNetworkInterfaces()返回本机全部端口,每一个NetworkInterface都会包含索引(index)、地址(Adress)、名称(Name),获取这些信息就可以通过其他三个构造方法来创建对应的NetworkInterface实例。
static void test3(){ try { //返回本机上所有端口 Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); while (networkInterfaces.hasMoreElements()){ NetworkInterface Ninterface = networkInterfaces.nextElement(); System.out.println("端口信息:"+Ninterface); System.out.println(String.format( "接口的最大传输单元(MTU):%d,是否环回接口:%b,是否是点对点接口:%b,是否启动并运行:%b,是否为虚拟接口(也称为子接口):%b,否支持多播:%b", Ninterface.getMTU(), Ninterface.isLoopback(), Ninterface.isPointToPoint(), Ninterface.isUp(), Ninterface.isVirtual(), Ninterface.supportsMulticast() )); //获取硬件地址 if(Ninterface.getHardwareAddress()!=null){ StringBuilder mac = new StringBuilder(); byte[] f = Ninterface.getHardwareAddress(); for(int i=0;i<f.length;i++){ String t = Integer.toHexString(0xff & f[i]); if(t.length()==1) mac.append("0"+t); else mac.append(t); if(i!=f.length-1) mac.append("-"); } System.out.println("硬件地址(如果有):"+mac); } //获取子接口 Enumeration<NetworkInterface> subInterfaces = Ninterface.getSubInterfaces(); int subc=0; while (subInterfaces.hasMoreElements()){ NetworkInterface subInterface = subInterfaces.nextElement(); //System.out.println("端口信息:"+subInterface); subc++; } System.out.println("子接口个数:"+subc); //getInetAddresses Enumeration<InetAddress> inetAddressEnumeration = Ninterface.getInetAddresses(); while (inetAddressEnumeration.hasMoreElements()){ System.out.println("对应的InetAddress:"+inetAddressEnumeration.nextElement()); } //List<InterfaceAddress> getInterfaceAddresses() List<InterfaceAddress> interfaceAddressList = Ninterface.getInterfaceAddresses(); for(int i=0;i<interfaceAddressList.size();i++){ System.out.println("对应的InterfaceAddress:"+interfaceAddressList.get(i)); } System.out.println("\n"); } //返回百度的端口--无法获取信息 String hostname = "www.baidu.com"; System.out.println("域名:"+hostname); InetAddress addresse = InetAddress.getByName(hostname); System.out.println("InetAddress:"+addresse); NetworkInterface networkInterface = NetworkInterface.getByInetAddress(addresse); System.out.println("NetworkInterface:"+networkInterface); } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } }