Java篇:Java网络编程(二)网络地址及端口

2 网络地址及端口

 

2.1 网络地址

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地址。
String getHostAddress() 以文本表示形式返回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 TYPEMETHOD AND DESCRIPTION
static InetSocketAddress createUnresolved(String host, int port) 从主机名和端口号创建未解析的套接字地址。
InetAddress getAddress() 获得 InetAddress 。
boolean equals(Object obj) 将此对象与指定对象进行比较。
String getHostName() 获得 hostname 。
String getHostString() 如果没有主机名(使用文字创建),则返回主机名或地址的String形式。
int getPort() 获取端口号。
boolean isUnresolved() 检查地址是否已解析成功。
int hashCode() 返回该套接字地址的哈希码。
String toString() 构造此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();
        }
    }

 

2.X 参考

posted @ 2022-01-02 15:03  l.w.x  阅读(638)  评论(0编辑  收藏  举报