文章目录
介绍
我们知道现在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。