基础网络知识
https://blog.csdn.net/Lzy410992/article/details/117123350
image.png

HTTP基于B/S的通信协议,HTTPS加入了数字签名,公私钥解密。HTTP/HTTPS属于应用层。
基于TCP/IP、Socket,不区分语言。
Socket属于通信技术,HTTP属于通信协议。基于Socket技术,使用HTTP交流

  • IPv4由32位组成
  • IPv6由128位组成

基本的IPv4网络划分如下
image

Java中,java.net包下的NetworkInterface类可以获得网络接口相关信息
image.png

NetworkInterface类

这个包的构造方法是default,意味着不能在不同包名下调用构造方法实例化,只能调用static工厂模式

    public static Enumeration<NetworkInterface> getNetworkInterfaces()

Enumeration< E >接口定义了一个可以迭代的范型JDK1.0时代的产物。定义了可以迭代查找的方法。和Iterator功能类似,但是没有Iterator功能全面,Iterator多了forEachRemaining和remove方法
如果要迭代Enumeration内部的类容可以使用类似Iterator的迭代方法

获得网络接口的基本信息

  • 获得网络设备在操作系统中的名称,代号
    多数以eth1、eth2等(eth为Erhernet以太网,局域网规范)
String getName()
  • 获得设备在操作系统中更详细的名称,包含厂商名称、网卡具体型号等。
String getDisplayName()
  • 获得网络接口的索引Index
    同名的接口在不同的机器上可以有不同的索引,未知为-1
int getIndex()
  • 判断是否为回调接口
boolean isLoopback() throws SocketException
  • 网络接口是否已启动并正在运行
boolean isUp() throws SocketException
  • 代码
//基本使用
class AA{
    public static void main(String[] args) {
        Enumeration<NetworkInterface> networkInterfaces=null;
        try {
            networkInterfaces = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e) {
            e.printStackTrace();
        }
        while (networkInterfaces.hasMoreElements()){
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            System.out.print(networkInterface.getName()+"   ");
            System.out.print(networkInterface.getDisplayName()+"   ");
            System.out.print(networkInterface.getIndex()+"   ");
            try {
                System.out.print(networkInterface.isUp()+"   ");
            } catch (SocketException e) {
                e.printStackTrace();
            }
            try {
                System.out.println(networkInterface.isLoopback());
            } catch (SocketException e) {
                e.printStackTrace();
            }
        }
    }
}

部分结果如下,和资源管理器中的资源也可以对应,不同系统下方法的实现不一样,可能会有差异
image.png
image.png

获取最大传输单元MTU大小

  • MTU
    最大传输单元,单位为Byte字节=8bit。如果过大则会因为发包时间间隔长,处理时间大,造成延迟。设置过小则包数量过多,效率低下。
    一般为1500字节,IPv6中为1280~65535
public int getMTU() throws SocketException
//获取最大传输单元大小
class AB{
    public static void main(String[] args) {
        Enumeration<NetworkInterface> networkInterfaces=null;
        try {
            networkInterfaces = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e) {
            e.printStackTrace();
        }
        while (networkInterfaces.hasMoreElements()){
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            System.out.print(networkInterface.getName()+"   ");
            System.out.print(networkInterface.getDisplayName()+"   ");
            try {
                System.out.println(networkInterface.getMTU());
            } catch (SocketException e) {
                e.printStackTrace();
            }
        }
    }
}

不同的场景默认的差距还是不小的
image.png

子接口与虚拟接口

  • 子接口
    在不添加新的物理网卡的基础上,基于原有的网络接口设备创建出一个虚拟的网络接口设备进行通信,由软件进行模拟,WIN不支持,Linux支持。
    虚拟子接口的名称通常是父网络接口的名称加上冒号(:),再加上子接口的标识号构成

  • 获得父接口
    如果它是物理(非虚拟)接口或没有父接口,则返回null 。

public NetworkInterface getParent()
  • 判断是否为虚拟接口
public boolean isVirtual()
  • 获得子接口信息
public Enumeration<NetworkInterface> getSubInterfaces()

获得网卡硬件地址MAC地址

  • 硬件地址
    又称物理地址,网络设备唯一标识,采用十六进制,48位表示。正规网卡厂商的MAC不会出现重复
//获得网卡的物理地址MAC
class AC {
    public static void main(String[] args) throws SocketException {
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        while (networkInterfaces.hasMoreElements()) {
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            byte[] hardwareAddress = networkInterface.getHardwareAddress();
            if (hardwareAddress != null) {
                for (int i = 0; i < hardwareAddress.length; i++) {
                    System.out.print(hardwareAddress[i]);
                }
                System.out.println();
            }
        }
    }
}

此时获得的MAC地址是十进制,转换成十六进制即可

判断是否为点对点(PointToPoint)设备

boolean isPointToPoint() throws SocketException

点对点即通过拨号或专线方式建立点对点连接发送数据

//判断是否为点对点
class BB{
    public static void main(String[] args) throws SocketException {
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        while (networkInterfaces.hasMoreElements()){
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            System.out.print(networkInterface.getDisplayName()+"  ");
            System.out.println(networkInterface.isPointToPoint());
        }
    }
}

image.png

判断是否支持多播

  • 单播:一对一、点对点传输
  • 广播:一对多,不区分目标,易造成无用的垃圾通信数据
  • 多播:即组播,在D类地址中使用,范围比广播要小
boolean supportsMulticast() throws SocketException
//是支持多播
class BC{
    public static void main(String[] args) throws SocketException {
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        while (networkInterfaces.hasMoreElements()){
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            System.out.print(networkInterface.getDisplayName()+" ");
            System.out.println(networkInterface.supportsMulticast());
        }
    }
}

NetworkInterface的其他static方法

  • 获取给定索引的网络接口
    public static NetworkInterface getByIndex(int index) throws SocketException
  • 搜索绑定了指定 Internet 协议 (IP) 地址的网络接口的便捷方法。
    public static NetworkInterface getByInetAddress(InetAddress addr) throws SocketException
  • 搜索具有指定名称的网络接口
    public static NetworkInterface getByName(String name) throws SocketException

InetAddress类

获得IP地址

通过DNS等解析查询

//返回具有绑定到此网络接口的 InetAddresses 的全部或子集的 Enumeration 的便捷方法。
public Enumeration<InetAddress> getInetAddresses()
//获取此网络接口的InterfaceAddresses的全部或子集的列表。
public java.util.List<InterfaceAddress> getInterfaceAddresses()

image.png
image.png
其中InetAddress的方法有

  • 获取此 IP 地址的完全限定域名 String getCanonicalHostName()
  • 获取此 IP 地址的主机名 String getHostName()
  • 以文本形式返回 IP 地址字符串 String getHostAddress()
  • 返回此InetAddress对象的原始 IP 地址。 结果按网络字节顺序排列:地址的最高顺序字节在getAddress()[0] byte[] getAddress()
//获得IP地址
class AD {
    public static void main(String[] args) throws SocketException {
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        while (networkInterfaces.hasMoreElements()) {
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            System.out.print(networkInterface.getDisplayName() + "  ");
            Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
            while (inetAddresses.hasMoreElements()) {
                InetAddress inetAddress = inetAddresses.nextElement();
                System.out.print(inetAddress.getCanonicalHostName() + "  " + inetAddress.getHostName() + "  " + inetAddress.getHostAddress() + "\n");
                byte[] address = inetAddress.getAddress();
                for (int i = 0; i < address.length; i++) {
                    System.out.print(address[i]);
                }
                System.out.print("\n");
            }
        }
    }
}

截取部分结果
image.png

获得本地主机和回环地址的基本信息

  • 本地主机地址
    返回本地主机的IP地址信息,如果有多个只返回第一个
    public static InetAddress getByName(String host)
        throws UnknownHostException {
        return InetAddress.getAllByName(host)[0];
    }

想返回多个可使用getAllByname()方法

  • 回环地址
    返回的 InetAddress 将代表 IPv4 环回地址 127.0.0.1 或 IPv6 环回地址 ::1。 返回的 IPv4 环回地址只是 127...* 形式的众多地址之一
    public static InetAddress getLoopbackAddress() {
        return impl.loopbackAddress();
    }
//获取本机地址localhost和回环地址
class CE {
    public static void main(String[] args) throws UnknownHostException {
        System.out.println(InetAddress.getLocalHost());
        InetAddress[] localhosts = InetAddress.getAllByName("localhost");
        for (int i = 0; i < localhosts.length; i++) {
            System.out.println(localhosts[i]);
        }
        InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
        for (int i = 0; i < localhosts.length; i++) {
            System.out.println(loopbackAddress);
        }
    }
}

image.png

根据主机名host获得IP地址

值得注意的是如果DNS被劫持或者所处的地点不同,解析同一个host的IP地址可能不同
host可以为计算机名/IP地址/域名
image.png

public static InetAddress getByName(String host)
        throws UnknownHostException {
        return InetAddress.getAllByName(host)[0];
    }
//根据host获得IP
class CF {
    public static void main(String[] args) throws UnknownHostException {
        //我的网站域名
        InetAddress byName = InetAddress.getByName("www.jtao.work");
        System.out.println(byName.getHostAddress());
        //百度域名
        System.out.println(InetAddress.getByName("www.baidu.com").getHostAddress());
    }
}

可以根据域名查找到服务器真实IP
image.png
curl后可以访问
image.png
image.png

根据主机host获得所有IP

//根据host获得所有IP
class CG {
    public static void main(String[] args) throws UnknownHostException {
        //我的网站域名
        InetAddress byName = InetAddress.getByName("www.jtao.work");
        System.out.println(byName.getHostAddress());
        //百度域名
        InetAddress[] baidu = InetAddress.getAllByName("www.baidu.com");
        for (int i = 0; i < baidu.length; i++) {
            System.out.println("百度IP:"+baidu[i]);
        }
        InetAddress[] jd = InetAddress.getAllByName("www.taobao.com");
        for (int i = 0; i < jd.length; i++) {
            System.out.println("淘宝IP:"+jd[i]);
        }
    }
}

淘宝2个IPv4,2个IPv6。
image.png

  • 根据host获得IP地址主机名称
//获得主机全限定名和主机名
class CH{
    public static void main(String[] args) throws UnknownHostException {
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost.getHostName());
        System.out.println(localHost.getCanonicalHostName());
        InetAddress[] localhosts = InetAddress.getAllByName("localhost");
        for (int i = 0; i < localhosts.length; i++) {
            System.out.print(localhosts[i]);
        }
        System.out.println();
        InetAddress[] localhosts1 = InetAddress.getAllByName("127.0.0.1");
        for (int i = 0; i < localhosts1.length; i++) {
            System.out.print(localhosts1[i]);
        }
        System.out.println();
        InetAddress byName = InetAddress.getByName("www.baidu.com");
        System.out.println(byName.getHostName());
        System.out.println(byName.getCanonicalHostName());
    }
}

image.png

InterfaceAddress类

取得网络接口对应的IP地址、子网掩码和广播地址等相关信息

InterfaceAddress 对应网络接口信息
InetAddress 对应IP地址信息

  • IPv4中
    可获得IP地址、子网掩码、广播地址
  • IPv6中
    可获得IP地址、网络前缀长度(子网掩码)
class BA{
    public static void main(String[] args) throws SocketException {
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        while (networkInterfaces.hasMoreElements()){
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            System.out.print(networkInterface.getName()+"  ");
            System.out.print(networkInterface.getDisplayName()+"/n");
            List<InterfaceAddress> interfaceAddresses = networkInterface.getInterfaceAddresses();
            interfaceAddresses.forEach(vo->{
                System.out.println(vo.getAddress());
                System.out.println(vo.getBroadcast());
                System.out.println(vo.getNetworkPrefixLength());
            });
        }
    }
}

NetworkInterface、InterfaceAddress、InetAddresses关系

  • 一个NetworkInterface包含多个InterfaceAddress对象
  • 一个InterfaceAddress只包含一个InetAddresses对象

这个家伙很懒,啥也没有留下😋