【网络编程】——Java实现(5)——访问系统网络的相关信息(Programmatic Access to Network Parameters)

这里是Java网络编程Java Socket编程相关的学习手记。这里按照官方的Java 8 Toturial教程的Custom Networking学习路径,对相关的一些内容进行解读(并不完全,如果有错请联系我,谢谢^ _ ^),同时在学习的过程中加入个人的理解与对代码运行的思考。

下面是整个专栏的文章链接,用于快速的导航。

摘要与说明

原文来自Java 8官方Tutorial
文章会加入自己的学习时想到的一些内容。

题目本来是:Programmatic Access to Network Parameters,这里我写成访问系统网络的相关信息,当然也可以写作访问网络参数的编程接口啦。不纠结了。。。

系统常常会有多个活跃的网络接口可用于连接,例如 { wired Ethernet802.11 b/g (wireless)bluetooth }。一些应用可能需要访问它们的信息来执行特定的网络活动。
{ 无线,有线,蓝牙 }

java.net.NetworkInterface类提供了访问这些信息的接口。

这篇文章就探讨一下这个类的一般用法,并且提供一些例子,比如说列出你的电脑上所有的网络接口(network interfaces),以及接口相关的信息如IP地址,网络状态

下面给出本文的导航,点击相应标题能够查看该小节的详细内容。

1. 什么是网络接口?(What Is a Network Interface?)

  • 介绍网络接口,以及解释你为什么想要使用它

2. 检索网络接口(Retrieving Network Interfaces)

  • 用一个例子来说明客户端程序如何检索(retrieve)机器上的所有网络接口

3. 列出网络接口地址(Listing Network Interface Addresses)

  • 教你怎么列出机器上所有网络接口的IP地址

4. 网络接口参数(信息)(Network Interface Parameters)

  • 教你怎么判定一个网络接口
    • 是否正在工作(is running)
    • 是否是一个回环接口(a loopback interface)
    • 是否是一个点到点的接口(a point-to-point interface)
    • 是否是一个虚拟接口(a virtual interface)
    • 是否支持多播(supports multicasting)

1. 什么是网络接口?(What Is a Network Interface?)

网络接口(network interface)是计算机互连或者网络互连的端点。网络接口一般来说是一个网络接口卡(NIC,network interface card),也就是我们日常所说的网卡,但是它(network interface)却不一定是以物理形式而存在的。相反,网络接口可能用软件来实现。拿回环接口( loopback interface)举个例子,IPv4的127.0.0.1和IPv6的 ::1都没有对应的物理设备,而是一种模拟网络接口的软件。回环接口通常在测试环境下使用。

java.net.NetworkInterface能表示软/硬两种形式的网络接口

NetworkInterface对于对多宿主系统(multi-homed system,带有多个网卡的系统)也是有用的。使NetworkInterface,你能指定某个网卡来进行特定的网络活动。

举个例子。假设你有一台配有两个网卡的机器,此时你想要发送数据给服务器。你能这样创建一个socket:
Socket soc = new java.net.Socket();
soc.connect(new InetSocketAddress(address, port));


前面的章节我们发送数据,都是默认由系统来选择某个网络接口来与外界进行通信。然而,如果你想自己指定某个网卡来发送数据,那么你需要查询系统以获取合适的接口,然后得到此接口的IP地址。通过上面方法创建socket后并且绑定我们获得的IP地址,系统就能使用此网络接口了。下面是代码实现:

NetworkInterface nif = NetworkInterface.getByName("bge0");
Enumeration<InetAddress> nifAddresses = nif.getInetAddresses();

Socket soc = new java.net.Socket();
soc.bind(new InetSocketAddress(nifAddresses.nextElement(), 0));
soc.connect(new InetSocketAddress(address, port));

你也能使用NetworkInterface来标识本地的网络接口在那个组播里。如:

NetworkInterface nif = NetworkInterface.getByName("bge0");
MulticastSocket ms = new MulticastSocket();
ms.joinGroup(new InetSocketAddress(hostname, port), nif);

NetworkInterface能被Java API用在许多其它方面,而不仅限于我们上面描述的两个例子。

2. 检索网络接口(Retrieving Network Interfaces)

NetworkInterface 类并没有public构造方法。因此,你不能使用new操作符来创建此类的实例,相反,可以使用static方法来获得(retrieve )系统网络接口的详细信息:getByInetAddress()getByName()getNetworkInterfaces()。前面两个方法已经用过了,获取IP地址和接口名。第三个方法,返回系统的所有接口列表。

网络接口能够有组织的被继承。NetworkInterface类包含两个方法就跟接口的继承相关:getParent()getSubInterfaces()。getParent方法返回接口的父NetworkInterface 。如果一个网络接口是子接口,那么getParent方法返回一个非空值(non-null)。getSubInterfaces()方法返回此网络接口的所有的子接口。

下面是一个程序例子,列出机器上的所有的网络接口名和子接口(如果存在的话)

import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class ListNIFs 
{
    public static void main(String args[]) throws SocketException {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        
        for (NetworkInterface netIf : Collections.list(nets)) {
            out.printf("Display name: %s\n", netIf.getDisplayName());
            out.printf("Name: %s\n", netIf.getName());
            displaySubInterfaces(netIf);
            out.printf("\n");
        }
    }

    static void displaySubInterfaces(NetworkInterface netIf) throws SocketException {
        Enumeration<NetworkInterface> subIfs = netIf.getSubInterfaces();
        
        for (NetworkInterface subIf : Collections.list(subIfs)) {
            out.printf("\tSub Interface Display name: %s\n", subIf.getDisplayName());
            out.printf("\tSub Interface Name: %s\n", subIf.getName());
        }
     }
}  

官方给出的输出例子。

Display name: bge0
Name: bge0
    Sub Interface Display name: bge0:3
    Sub Interface Name: bge0:3
    Sub Interface Display name: bge0:2
    Sub Interface Name: bge0:2
    Sub Interface Display name: bge0:1
    Sub Interface Name: bge0:1

Display name: lo0
Name: lo0

然而,下面是我的电脑的输出结果,因为虚拟机的原因,输出的东西有点多。没有Sub Interface接口。

Display name: Software Loopback Interface 1
Name: lo

Display name: Microsoft Hosted Network Virtual Adapter
Name: wlan0

Display name: Microsoft ISATAP Adapter
Name: net0

Display name: Microsoft ISATAP Adapter #4
Name: net1

Display name: Microsoft ISATAP Adapter #2
Name: net2

Display name: VMware Virtual Ethernet Adapter for VMnet8
Name: eth0

Display name: Realtek PCIe FE Family Controller
Name: eth1

Display name: Intel(R) Dual Band Wireless-AC 3160
Name: wlan1

Display name: Microsoft ISATAP Adapter #3
Name: net3

Display name: WAN Miniport (SSTP)
Name: net4

Display name: WAN Miniport (IP)
Name: eth2

Display name: WAN Miniport (IKEv2)
Name: net5

Display name: VMware Virtual Ethernet Adapter for VMnet1
Name: eth3

Display name: WAN Miniport (PPPOE)
Name: ppp0

Display name: WAN Miniport (PPTP)
Name: net6

Display name: Microsoft Kernel Debug Network Adapter
Name: eth4

Display name: Microsoft Wi-Fi Direct Virtual Adapter
Name: wlan2

Display name: WAN Miniport (Network Monitor)
Name: eth5

Display name: Remote NDIS based Internet Sharing Device
Name: eth6

Display name: WAN Miniport (L2TP)
Name: net7

Display name: WAN Miniport (IPv6)
Name: eth7

Display name: Microsoft Teredo Tunneling Adapter
Name: net8

Display name: Realtek PCIe FE Family Controller-WFP Native MAC Layer LightWeight Filter-0000
Name: eth8

Display name: Realtek PCIe FE Family Controller-VirtualBox NDIS Light-Weight Filter-0000
Name: eth9

Display name: Realtek PCIe FE Family Controller-Liebao Wifi NAT Driver-0000
Name: eth10

Display name: Realtek PCIe FE Family Controller-QoS Packet Scheduler-0000
Name: eth11

Display name: Realtek PCIe FE Family Controller-WFP 802.3 MAC Layer LightWeight Filter-0000
Name: eth12

Display name: Intel(R) Dual Band Wireless-AC 3160-WFP Native MAC Layer LightWeight Filter-0000
Name: wlan3

Display name: Intel(R) Dual Band Wireless-AC 3160-Virtual WiFi Filter Driver-0000
Name: wlan4

Display name: Intel(R) Dual Band Wireless-AC 3160-Native WiFi Filter Driver-0000
Name: wlan5

Display name: Intel(R) Dual Band Wireless-AC 3160-VirtualBox NDIS Light-Weight Filter-0000
Name: wlan6

Display name: Intel(R) Dual Band Wireless-AC 3160-Liebao Wifi NAT Driver-0000
Name: wlan7

Display name: Intel(R) Dual Band Wireless-AC 3160-QoS Packet Scheduler-0000
Name: wlan8

Display name: Intel(R) Dual Band Wireless-AC 3160-WFP 802.3 MAC Layer LightWeight Filter-0000
Name: wlan9

Display name: Microsoft Hosted Network Virtual Adapter-WFP Native MAC Layer LightWeight Filter-0000
Name: wlan10

Display name: Microsoft Hosted Network Virtual Adapter-Native WiFi Filter Driver-0000
Name: wlan11

Display name: Microsoft Hosted Network Virtual Adapter-VirtualBox NDIS Light-Weight Filter-0000
Name: wlan12

Display name: Microsoft Hosted Network Virtual Adapter-Liebao Wifi NAT Driver-0000
Name: wlan13

Display name: Microsoft Hosted Network Virtual Adapter-QoS Packet Scheduler-0000
Name: wlan14

Display name: Microsoft Hosted Network Virtual Adapter-WFP 802.3 MAC Layer LightWeight Filter-0000
Name: wlan15

Display name: Microsoft Wi-Fi Direct Virtual Adapter-WFP Native MAC Layer LightWeight Filter-0000
Name: wlan16

Display name: Microsoft Wi-Fi Direct Virtual Adapter-Native WiFi Filter Driver-0000
Name: wlan17

Display name: Microsoft Wi-Fi Direct Virtual Adapter-VirtualBox NDIS Light-Weight Filter-0000
Name: wlan18

Display name: Microsoft Wi-Fi Direct Virtual Adapter-Liebao Wifi NAT Driver-0000
Name: wlan19

Display name: Microsoft Wi-Fi Direct Virtual Adapter-QoS Packet Scheduler-0000
Name: wlan20

Display name: Microsoft Wi-Fi Direct Virtual Adapter-WFP 802.3 MAC Layer LightWeight Filter-0000
Name: wlan21

3. 列出网络接口地址(Listing Network Interface Addresses)

你能从接口获取的最有用的信息之一就是IP地址了。你能通过NetworkInterface实例来获取IP地址。下面有两个方法。一种是通过getInetAddresses()方法返回InetAddress类型的枚举类(Enumeration of InetAddress,Enumeration<NetworkInterface>)。第二种方法是通过getInterfaceAddresses()返回java.net.InterfaceAddress实例list,当你不仅仅只是想获取接口的ip,还想获取其它信息的时候可以使用这种方法,例如:IPv4中的子网掩码(subnet mask),广播地址(broadcast address),IPv6中的网络前缀长度(network prefix length)。

下面是一个程序的例子,列出所有网络接口以及它的IP地址:

import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class ListNets {

    public static void main(String args[]) throws SocketException {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netint : Collections.list(nets))
            displayInterfaceInformation(netint);
    }

    static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
        out.printf("Display name: %s\n", netint.getDisplayName());
        out.printf("Name: %s\n", netint.getName());
        Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
        for (InetAddress inetAddress : Collections.list(inetAddresses)) {
            out.printf("InetAddress: %s\n", inetAddress);
        }
        out.printf("\n");
     }
}  

官方给出的一个输出例子

Display name: TCP Loopback interface
Name: lo
InetAddress: /127.0.0.1

Display name: Wireless Network Connection
Name: eth0
InetAddress: /192.0.2.0

4. 网络接口参数(信息)(Network Interface Parameters)

你能获得一个网络接口更多的网络参数,而不仅仅只是接口名,IP地址。

你能通过isUP()方法来查看一个接口是否正在运行。下面的方法可以获知网络接口的类型:

  • isLoopback()用来查看一个接口是否是回环接口(loopback interface)
  • isPointToPoint()用来查看接口是否是点到点接口( point-to-point interface.)
  • isVirtual()查看接口是否是虚拟接口(virtual interface)

supportsMulticast()方法可以查看接口是否支持多播。
getHardwareAddress()方法能获取接口的物理地址,通常情况下叫做MAC地址
getMTU()获取接口的最大传输单元(Maximum Transmission Unit (MTU),也就是单个数据包的最大字节数。

下面是代码例子:

import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class ListNetsEx {

    public static void main(String args[]) throws SocketException {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netint : Collections.list(nets))
            displayInterfaceInformation(netint);
    }

    static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
        out.printf("Display name: %s\n", netint.getDisplayName());
        out.printf("Name: %s\n", netint.getName());
        Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
        
        for (InetAddress inetAddress : Collections.list(inetAddresses)) {
            out.printf("InetAddress: %s\n", inetAddress);
        }
       
        out.printf("Up? %s\n", netint.isUp());
        out.printf("Loopback? %s\n", netint.isLoopback());
        out.printf("PointToPoint? %s\n", netint.isPointToPoint());
        out.printf("Supports multicast? %s\n", netint.supportsMulticast());
        out.printf("Virtual? %s\n", netint.isVirtual());
        out.printf("Hardware address: %s\n",
                    Arrays.toString(netint.getHardwareAddress()));
        out.printf("MTU: %s\n", netint.getMTU());
        out.printf("\n");
     }
}  

官方给出的输出例子:

Display name: bge0
Name: bge0
InetAddress: /fe80:0:0:0:203:baff:fef2:e99d%2
InetAddress: /129.156.225.59
Up? true
Loopback? false
PointToPoint? false
Supports multicast? false
Virtual? false
Hardware address: [0, 3, 4, 5, 6, 7]
MTU: 1500

Display name: lo0
Name: lo0
InetAddress: /0:0:0:0:0:0:0:1%1
InetAddress: /127.0.0.1
Up? true
Loopback? true
PointToPoint? false
Supports multicast? false
Virtual? false
Hardware address: null
MTU: 8232
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值