【网络编程】学习系列(一)NetWrokInterface介绍

介绍

我们知道现在B/S架构大多是基于HTTP协议的,虽然HTTP在开发速度很快,但是运行的效率不是很快,而且HTTP在通信原理上底层也是Socket。

注意:Soket不是协议,而是一种通信技术。Socket技术是在TCP/IP的基础上进行的。Sokcet主要就是为了通信而生,而协议是为了读懂传输来的数据。

任何语言实现套接字(Socket),都必须要与网络接口进行交互,而在网路交互的时候获取网络接口的信息就很重要。

1.NetWrokInterface类

此类包含了网络接口的名称和IP地址列表

想要NetWrokInterface对象,就必须通过此类的

public static Enumeration getNetWrokInterface()方法,作用是返回此机器上的所有接口

1.1 方法的介绍

1.1.1 获取网络接口的基本信息

public String getName()

获取网络设配在操作系统中的名称,该名称仅仅是一个代号,多数以eth开头,比如eth0、eth1

public String getDdisplayName()

获取设备在操作系统中的名称。此方法返回的字符穿包含了厂商名称个网卡具体型号等相关信息。

public int getIndex()

返回网络接口的索引,此索引在不同的操作系统中可能不太一样,所以大于或等于0,

但是如果索引位置就返回-1

public boolean isUp

判断网络接口已开启并正常工作

public boolena isLoopback()

判断该网络是否为回环接口

在学习SOCKET时,需要留意lockhost是一个域名,必须把域名解析为127.0.0.1,才能进行传输与通信,这个解析过程由host文件完成

测试代码如下所示

@Test
public void test1() throws SocketException {
    Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
    while(networkInterfaces.hasMoreElements()){
        NetworkInterface networkInterface = networkInterfaces.nextElement();
        System.out.println("getName名称 = "+networkInterface.getName());

        System.out.println("getDisplayName 名称 = "+networkInterface.getDisplayName());

        System.out.println("getIndex 获取接口的索引 = "+networkInterface.getIndex());

        System.out.println("isUp是否开始运行 = "+networkInterface.isUp());

        System.out.println("isLoopback是否为回环地址 = "+networkInterface.isLoopback());
        System.out.println("=======================================================");
    }
}

1.1.2获取MTU大小

MTU(Maximum Transmission Unit)最大传输单元:用来规定网络最大传输的数据包,单位为字节。

以太网的网卡大多默认在1500字节,在IPV6协议中,MTU的范围为280-65535.MTU设置的大小与传输效率有关,如果MTU设置大值,则传输速度很快,因为发送的数据包数量少了,但是延迟很大,因为对方需要一点点的处理数据,如果设置小了,传输速度太慢,建议不要随意更改网卡的MTU值

如果MTU = -1表名网络接口处于禁用状态

@Test
public void test1() throws SocketException {
    Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
    while(networkInterfaces.hasMoreElements()){
        NetworkInterface networkInterface = networkInterfaces.nextElement();
        System.out.println("getName名称 = "+networkInterface.getName());

        System.out.println("getDisplayName 名称 = "+networkInterface.getDisplayName());

        System.out.println("MTU -> "+networkInterface.getMTU());
    }
}

1.1.3 子接口处理

public Enumeration getSubInterfaces()方法

该方法的作用是取得子接口

什么是子接口?

子接口就是在不添加新的物理网卡的基础上,基于原有的网络接口创建虚拟的网络接口设备进行通信,Window操作系统不支持子接口,而Linux支持

public boolean isVirtual()

判断当前的网络接口是否为虚拟子接口。在linux操作系统上,虚拟子接口作为物理接口的子接口被创建,并给予不同的设置(如IP地址和MTU等)。

windows上一定返回false,因为windows上不支持虚拟子接口

注意:

  • 虚拟接口没有父网络接口
  • 虚拟子接口有父网络接口
  • 虚拟接口不一定是虚拟子接口,但是虚拟子接口一定是虚拟接口
@Test
public void test1() throws SocketException {
    Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
    while(networkInterfaces.hasMoreElements()){
        NetworkInterface networkInterface = networkInterfaces.nextElement();
        System.out.println("getName名称 = "+networkInterface.getName());

        System.out.println("getDisplayName 名称 = "+networkInterface.getDisplayName());

        System.out.println("isVirtual -> "+networkInterface.isVirtual());
    }
}

在linux上创建虚拟子接口的命令

Systemctl stop NtworkManager.service
ip addr add 192.168.1.4 dev wlp3s0 label wlp3s0:0

1.1.4 获取硬件地址

public byte[] getHardWareAddress()方法

获取网卡的硬件地址?硬件地址也称为物理地址或MAC地址,用来定义网络设备的位置,采用16进制表示,一共48位

如下代码所示

使用toHexString将其转为16进制,但是如果是负数假设为-65此时需要256加上这个数,将其变为正的就是 256+ (-65)然后对该结果进行26进制的转换

@Test
    public void test1() throws SocketException {
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        while(networkInterfaces.hasMoreElements()){
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            System.out.println("getName名称 = "+networkInterface.getName());

            System.out.println("getDisplayName 名称 = "+networkInterface.getDisplayName());

            byte[] hardwareAddress = networkInterface.getHardwareAddress();

            if(hardwareAddress != null){
                for(int i = 0; i<hardwareAddress.length;i++){
                    String temp = "";
                    if(hardwareAddress[i] < 0){
                        temp = Integer.toHexString(256+hardwareAddress[i]);
                    }else{
                        temp = Integer.toHexString(hardwareAddress[i]);
                    }
                    System.out.print(temp + " ");
                }
                System.out.println();
            }

            System.out.println(Arrays.toString(hardwareAddress));

            System.out.println("---------------------------------");
        }
    }

1.1.5获取IP地址

**public Enumeration getInetAddress()**方法的作用:获得绑定到此网络接口的InetAddress列表。

InetAddress可以表示成IP地址,一个网络接口可以有多个IP地址。

InetAddress有两个子类:Inet4Address和Inet6Address,用来描述IPV4和IPV6的地址信息。

注意:InetAddress不能直接实例化,必须借助工厂方法。如下所示

在这里插入图片描述

1.获得Ip地址的基本信息

getCannonicalHostName()

获取此IP地址的完全限定域名

完全限定域名指主机名加上全路径,全路径流出序列中所有域成员

getHostName()

获取ip地址的主机名

getHostAddress()

获取IP地址字符串

getAddress()

获取InetAddress对象的原始IP地址,返回byte数组

2.获取本地主机和回环地址的基本信息

static InetAddress getLocalhost()方法的作用:返回本地主机的IP地址信息。如果本机拥有多个IP,则getLocalhost()方法只返回下表为0的第一个IP,如果需要全部返回则需要使用getAllByName()方法。

@Test
public void test5() throws UnknownHostException {
    InetAddress inetAddress = InetAddress.getLocalHost();
    System.out.println(inetAddress.getHostAddress());
}

3.根据主机名获得IP地址

static InetAddress getByName(String host)

在给定主机名的情况下,确定主机的IP地址。参数HOST可以是主机名、IP地址、域名。

代码如下

@Test
public void test3() throws UnknownHostException {
    System.out.println("根据主机名获取--------");
    InetAddress inetAddress = InetAddress.getByName("MS-ZSRYCMZZQEUY");
    System.out.println(inetAddress.getHostAddress());
    System.out.println("根据域名获取--------");
    InetAddress inetAddress1 = InetAddress.getByName("localhost");
    System.out.println(inetAddress1.getHostAddress());
    System.out.println("根据IP地址获取--------");
    InetAddress inetAddress2 = InetAddress.getByName("192.168.2.1");
    System.out.println(inetAddress2.getHostName());
}

4.根据主机名获取所有的IP地址

static InetAddress[] getAllByName(String host)。在给定host的情况下返回所有的InetAddress所组成的数组。

@Test
public void test4() throws UnknownHostException {
    InetAddress[] inetAddresses = InetAddress.getAllByName("MS-ZSRYCMZZQEUY");
    Arrays.stream(inetAddresses).forEach( i ->{
        System.out.println(i.getHostAddress());
        System.out.println("----------------");
    });
}

5.根据IP地址byte[] addr获得InetAddress对象

在给定原始Ip地址(字节数组)的情况返回InetAddress对象。

@Test
public void test6() throws UnknownHostException {
    byte[] bytes = new byte[]{-64,-88,-95,1};
    InetAddress address = InetAddress.getByAddress(bytes);
    System.out.println(address.getHostAddress());
}

6.根据主机名和初始IP地址获得InetAddress对象

static InetAddress getByAddress(String host,byte[] addr)方法的作用:根据提供的host和IP地址创建InetAddress

@Test
public void test7() throws UnknownHostException {
    byte[] bytes = new byte[]{-64,-88,-95,20};
    InetAddress byAddress = InetAddress.getByAddress("dong", bytes);
    System.out.println(byAddress.getHostAddress());
    System.out.println(byAddress.getHostName());
}

注意:host的有效性不回验证,host就是表示IP的一个标识,标识这个IP所属的主机名是host

7.获取权限主机名和主机名

getCanonicalHostName()方法失去的完全限定域名

getName()是取得主机别名

如下所示

结果getCanonicalHostName打印IP地址,getName打印的是www.baidu.com,

getCanonicalHostName的结果和DNS有很大关系。

@Test
public void test8() throws UnknownHostException {
    InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
    System.out.println(inetAddress.getHostAddress());
    System.out.println(inetAddress.getCanonicalHostName());
    System.out.println(inetAddress.getHostName());
}

1.1.6 InterfaceAddress类的使用

public List getInterfaceAddress()方法:

获取网络接口的InterfaceAddresses列表。通过InterfaceAddress类中的方法可以获得网络接口对应的IP地址、子网掩码和广播地址等。

InetAddress getAddress()方法:

返回InterfaceDress的InetAddress

InetAddress getBroadcast()方法:

返回Interface广播地址的InetAddress。由于只有IPV4具有广播地址,因此对于IPV6网络将返回Null.

short getNetworkPrefixLength()方法:

返回此InterfaceAddress网络前缀的长度。网络前缀就是子网掩码

InetAddress类对应的是IP地址信息的,而InterfaceAddress类是对应网络接口信息对的,可以在InterfaceAddress对象中获得IP地址的InetAddress对象信息,以及多播地址的InetAddress信息、子网等。

代码使用如下所示

@Test
public void test9() throws SocketException {
    Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
    while(networkInterfaces.hasMoreElements()){
        NetworkInterface networkInterface = networkInterfaces.nextElement();
        List<InterfaceAddress> interfaceAddresses = networkInterface.getInterfaceAddresses();
        interfaceAddresses.forEach(i -> {
            InetAddress broadcast = i.getBroadcast();
            if(broadcast != null){
                System.out.println("broadCast hostNam == "+broadcast.getHostName());
                System.out.println("broadCast address == "+broadcast.getHostAddress());
            }
            short prefixLength = i.getNetworkPrefixLength();
            System.out.println("prefix length -> "+prefixLength);
            InetAddress address = i.getAddress();
            if(address != null){
                System.out.println("InetAddresss hostName ->" + address.getHostName());
                System.out.println("InetAddresss hostAddress ->" + address.getHostAddress());
            }
            System.out.println("-------------------------------------------------");
        });
        System.out.println("========================");
    }
}

NetworkInterface、InterfaceAddress、InetAddress三者关系如下

一个NetworkInterface可以有多个InterfaceAddress

一个InterfaceAddress只能有一个InetAddress

在这里插入图片描述

1.1.7 判断是否为点对点设配

public boolean isPointToPoint()

判断当前的而网络设备是不是点对点设备。什么是point to point(点对点)?他被设计的主要Udine通过拨号或专线方式简历点对点连接以法师那个数据。

代码如下所示:

@Test
public void test10() throws SocketException {
    Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
    while(networkInterfaces.hasMoreElements()){
        NetworkInterface networkInterface = networkInterfaces.nextElement();
        System.out.println("getName => "+networkInterface.getName());
        System.out.println("getDisplayName => "+networkInterface.getDisplayName());
        System.out.println("point to point ? => "+ networkInterface.isPointToPoint());
        System.out.println("=========================");
    }
}

1.1.8 是否支持多播

public boolean supportsMulticast()方法

判断当前的网络设备是否支持多播

什么是单播?单播大多都是点对点式的网络,如打开网页、发送邮件和两人网络聊天,都是在使用点对点方式传输数据。

什么是广播?广播是一种一对多的形式,对所有的计算机发送数据,频繁广播可能造成网络风暴,是网络变慢

什么是多播?也成组播,也是一种一种一对多的网络,从组播的名字来看,可以对某些计算机分配多播IP地址进行多播分组,只针对多播组内进行发偶是那个数据。多播比广播更有效率因为目标是确定的,而不是全部的计算机。在网络中多播一般通过多播IP地址实现,多播IP地址是D类IP地址即224.0.0.0 ~ 239.255.255.255之间

测试代码如下

@Test
public void test11() throws SocketException {
    Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
    while(networkInterfaces.hasMoreElements()){
        NetworkInterface networkInterface = networkInterfaces.nextElement();
        System.out.println("getName -> "+networkInterface.getName());
        System.out.println("displayName" + networkInterface.getDisplayName());
        System.out.println("supportsMulticast -> "+networkInterface.supportsMulticast());
        System.out.println("------------------------");
    }
}

1.2 NetworkInterface类的静态方法

处了之前介绍的getNetworkInterfaces()方法之外还有其他三个静态方法

1.2.1 根据索引获得NetworkInterface对象

public static NetworkInterface getByIndex(int index)方法的作用:根据指定的索引返回NetworkInterface对象

@Test
public void test12() throws SocketException {
    NetworkInterface networkInterface = NetworkInterface.getByIndex(1);
    System.out.println(networkInterface.getDisplayName());
    System.out.println(networkInterface.getName());
}

1.2.2 根据网络接口名称获得NetworkInterface对象

public static NetworkInterface getByName(String name)根据指定的NetworkInterface的名字获得此对象

@Test
public void test12() throws SocketException {
    NetworkInterface networkInterface = NetworkInterface.getByName("lo");
    System.out.println(networkInterface.getDisplayName());
    System.out.println(networkInterface.getName());
}

1.2.3 根据InetAddress获得NetworkInterface对象

public static NEtworkInterface getByInetAddress(InetAddress addr)

根据IP地址信息对象InetAddress获得networkInterface对象

@Test
public void test12() throws SocketException, UnknownHostException {
    InetAddress localhost = InetAddress.getByName("localhost");
    NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localhost);
    System.out.println(networkInterface.getDisplayName());
    System.out.println(networkInterface.getName());
}

注意

我们知道一个NetworkInterface可以对应多个InetAddress的,其实一个IP地址可以绑定到多个NetworkInterface的,这样可以提升网络冗余、负载等。

这时候由于由于InetAddress对应多个NetworkInterface所以不确定会返回哪个NetworkInterface。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值