在Java中使用网络接口
最后修改:2019年5月8日
1.概述
在本文中,我们将专注于网络接口以及如何在Java中以编程方式访问它们。
简单地说,一个网络接口是设备与其任何网络连接之间的互连点。
在日常语言中,我们用术语网络接口卡(NICs)来指代它们——但它们并不都必须是硬件形式。
例如,流行的本地主机IP127.0.0.1我们在测试web和网络应用程序时经常使用的是loopback接口——它不是一个直接的硬件接口。
当然,系统通常具有多个有源网络连接,例如有线以太网,WiFi,蓝牙等。
在Java中,我们可以用来直接与它们进行交互的主API是java.net.network interface.类。因此,为了快速开始,让我们导入完整的包:
导入java.net。*;
2.为什么要访问网络接口?
大多数Java程序可能无法直接与它们交互;但是,当我们需要这种低级访问时,有特殊情况。
这些最突出的是系统有多个牌,并且您想要拥有的地方选择特定接口来使用套接字的自由。在这种情况下,我们通常知道名称,但不一定知道IP地址。
通常,当我们想要使套接字连接到特定的服务器地址时:
Socket Socket = new Socket();socket.connect(新inetsocketaddress(地址,端口));
通过这种方式,系统将选择一个合适的本地地址,绑定到它,并通过它的网络接口与服务器通信。然而,这种方法不允许我们选择我们自己的。
我们在这里做一个假设;我们不知道地址,但知道名字。出于演示的目的,让我们假设我们想要通过loopback接口连接,按照约定,它的名称是罗至少在Linux和Windows系统上,它是LO0.:
NetworkInterface nif = networkInterface.getByName(“lo”);枚举 nifaddresses = nif.getInetAddresses();Socket Socket = new Socket();socket.bind(new inetsocketaddress(nifaddresses.nextElement(),0));socket.connect(新inetsocketaddress(地址,端口));
所以我们检索附加的网络接口罗首先,检索附加到它的地址,创建一个套接字,将它绑定到任何我们在编译时不知道的枚举地址,然后连接。
一种NetworkInterface对象包含分配给它的名称和一组IP地址。因此,与这些地址中的任何一个都将保证通过此接口进行通信。
这并没有真正对API特别说出任何特别的事情。金宝搏官网188be我们知道,如果我们希望我们的本地地址是localhost,那么如果我们刚刚添加了绑定代码,则第一个代码段就足够了。
此外,自Localhost有一个知名地址以来,我们永远不会真正使用几个步骤,127.0.0.1我们可以轻松将套接字绑定到它。
但是,在您的情况下,罗也许可以代表其他的接口,如蓝牙-net1.,无线网络 -Net0.或以太网 -eth0。在这种情况下,您无法在编译时知道IP地址。
3.检索网络接口
在本节中,我们将浏览其他可用的API,用于检索可用接口。在上一节中,我们只看到了这些方法之一;这getbyname()静态方法。
值得注意的是NetworkInterface类没有任何公共构造函数,所以我们当然无法创建一个新实例。相反,我们将使用可用的API来检索一个。
我们查看到目前为止的API用于通过指定的名称搜索网络接口:
@Test public void givenname_whenreturnnsnetworkinterface_thencorrect () {NetworkInterface nif = NetworkInterface. getbyname ("lo");assertNotNull (nif);}
它返回零如果没有名称:
@test public voidedinexistentname_whenreturnsnull_thencorrect(){networkinterface nif = networkInterface.getbyname(“inexistent_name”);assertnull(nif);}
第二个API是getByInetAddress (),它还要求我们提供已知参数,这次我们可以提供IP地址:
@Test public void givenip_whenreturnnsnetworkinterface_thencorrect () {byte[] ip = new byte[] {127,0,0,1};NetworkInterface nif = NetworkInterface。getByInetAddress (InetAddress.getByAddress (ip));assertNotNull (nif);}
或主机名:
@Test public void givenhostname_whenreturnnsnetworkinterface_thenccorrect () {NetworkInterface nif = NetworkInterface。getByInetAddress (InetAddress.getByName (" localhost "));assertNotNull (nif);}
或者如果你对localhost很明确:金宝搏官网188be
@Test public void givenlocalhost_whenreturnnsnetworkinterface_thenccorrect () {NetworkInterface nif = NetworkInterface。getByInetAddress (InetAddress.getLocalHost ());assertNotNull (nif);}
另一种替代方案也是显式使用环回接口:
@test public void给gentloopback_whenreturnsnetworkInterface_thencorrect(){networkinterface nif = networkInterface.getByInetAddress(inetaddress.getloopbackaddress());assertNotNull (nif);}
只有Java 7以来才能获得的第三种方法是通过其索引获取网络接口:
NetworkInterface nif = networkInterface.getByIndex(INT索引);
最后一种方法是使用getnerworkinterfaces.API。它返回A.枚举系统中所有可用的网络接口。我们需要在循环中检索返回的对象,标准的习惯用法是使用a列表:
枚举 net = NetworkInterface. getnetworkinterfaces ();for (NetworkInterface nif: Collections.list(nets)){//使用网络接口做一些事情}
4.网络接口参数
在检索到它的对象后,我们可以得到很多有价值的信息。最有用的是分配给它的IP地址列表。
我们可以使用两个api获得IP地址。第一个API是getInetAddresses ()。它返回A.枚举的inetaddress.我们认为合适的实例:
@test public voidedInterface_whenreturnsinetaddresses_thencorrect(){networkinterface nif = networkInterface.getbyname(“lo”);枚举 addramentenum = nif.getInetAddresses();inetaddress地址= addressenum.nextElement();assertequals(“127.0.0.1”,地址.Gethostaddress());}
第二个API是getInterfaceAddresses ()。它返回一个列表的InterfaceAddress比inetaddress.实例。例如,除了IP地址外,你可能会对广播地址感兴趣:
@Test public void giveninterface_whenreturnnsinterfaceaddresses_thencorrect () {NetworkInterface nif = NetworkInterface. getbyname ("lo");List addressEnum = nif.getInterfaceAddresses();InterfaceAddress地址= addressEnum.get(0);InetAddress localAddress = address.getAddress ();InetAddress broadCastAddress = address.getBroadcast();assertequal (127.0.0.1, localAddress.getHostAddress ());assertequal(“127.255.255.255 broadCastAddress.getHostAddress ());}
我们可以访问超过分配给它的名称和IP地址的接口的网络参数。金宝搏官网188be要检查它是否已启动并运行:
@Test公共voidedInterface_whenchecksifup_thencorrect(){networkinterface nif = networkInterface.getbyname(“lo”);asserttrue(nif.isup());}
要检查它是否是环回接口:
@test public voidedInteriantface_whenchecksifloopback_thencorrect(){networkinterface nif = networkInterface.getbyname(“lo”);asserttrue(nif.isloopback());}
检查它是否代表点对点的网络连接:
@test公共voidedInterface_whenchecksifpointtopoint_thencorrect(){networkinterface nif = networkInterface.getbyname(“lo”);assertfalse(nif.ispointtopoint());}
或者如果它是虚拟接口:
@Test public void giveninterface_whenchecksifvirtual_thencright () {NetworkInterface nif = NetworkInterface. getbyname ("lo");assertFalse (nif.isVirtual ());}
检查是否支持多播:
@Test public void giveninterface_whenchecksmulticastsupport_thenccorrect () {NetworkInterface nif = NetworkInterface. getbyname ("lo");assertTrue (nif.supportsMulticast ());}
或者检索其物理地址,通常称为MAC地址:
@Test公共voidedInterface_whengetsmacaddress_thengorrect(){networkinterface nif = networkInterface.getbyname(“lo”);byte [] bytes = nif.gethardwareaddress();assertnotnull(bytes);}
另一个参数是最大传输单元,它定义了可以通过该接口传输的最大数据包大小:
@test公共voidedInterface_whengetsmtu_thencorrect(){networkinterface nif = networkInterface.getbyname(“net0”);int mtu = nif.getmtu();assertequals(1500,mtu);}
结论
在本文中,我们已经显示了网络接口,如何以编程方式访问它们以及我们需要访问它们的原因。
本文中使用的完整源代码和示例可在Github项目。