基础网络知识
https://blog.csdn.net/Lzy410992/article/details/117123350
HTTP基于B/S的通信协议,HTTPS加入了数字签名,公私钥解密。HTTP/HTTPS属于应用层。
基于TCP/IP、Socket,不区分语言。
Socket属于通信技术,HTTP属于通信协议。基于Socket技术,使用HTTP交流
- IPv4由32位组成
- IPv6由128位组成
基本的IPv4网络划分如下
Java中,java.net包下的NetworkInterface类可以获得网络接口相关信息
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();
}
}
}
}
部分结果如下,和资源管理器中的资源也可以对应,不同系统下方法的实现不一样,可能会有差异
获取最大传输单元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();
}
}
}
}
不同的场景默认的差距还是不小的
子接口与虚拟接口
-
子接口
在不添加新的物理网卡的基础上,基于原有的网络接口设备创建出一个虚拟的网络接口设备进行通信,由软件进行模拟,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());
}
}
}
判断是否支持多播
- 单播:一对一、点对点传输
- 广播:一对多,不区分目标,易造成无用的垃圾通信数据
- 多播:即组播,在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()
其中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");
}
}
}
}
截取部分结果
获得本地主机和回环地址的基本信息
- 本地主机地址
返回本地主机的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);
}
}
}
根据主机名host获得IP地址
值得注意的是如果DNS被劫持或者所处的地点不同,解析同一个host的IP地址可能不同
host可以为计算机名/IP地址/域名
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
curl后可以访问
根据主机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。
- 根据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());
}
}
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对象
Comments | 0 条评论