概述
在网络编程中,有时我们需要判断两台机器之间的连通性,或者说是一台机器到另一台机器的网络可达性。在系统层面的测试中,我们常常用Ping命令来做验证。尽管Java提供了比较丰富的网络编程类库(包括在应用层的基于URL的网络资源读取,基于TCP/IP层的Socket编程,以及一些辅助的类库),但是没有直接提供类似Ping命令来测试网络连通性的方法。本文将介绍如何通过Java已有的API,编程实现各种场景下两台机器之间的网络可达性判断。在下面的章节中,我们会使用Java网络编程的一些类库java.net.InetAddress和java.net.Socket,通过例子解释如何模拟Ping命令。
简单判断两台机器的可达性
一般情况下,我们仅仅需要判断从一台机器是否可以访问(Ping)到另一台机器,此时,可以简单的使用 Java 类库中 java.net.InetAddress 类来实现,这个类提供了两个方法探测远程机器是否可达
- booleanisReachable(inttimeout)
-
booleanisReachable(NetworkInterfacenetif,intttl,inttimeout)
-
简单说来,上述方法就是通过远端机器的IP地址构造InetAddress对象,然后调用其isReachable方法,测试调用机器和远端机器的网络可达性。注意到远端机器可能有多个IP地址,因而可能要迭代的测试所有的情况。
清单1:简单判断两台机器的可达性
- voidisAddressAvailable(Stringip){
-
try{
-
InetAddressaddress=InetAddress.getByName(ip);
-
-
if(addressinstanceofjava.net.Inet4Address){
-
System.out.println(ip+"isipv4address");
-
}else
-
if(addressinstanceofjava.net.Inet6Address){
-
System.out.println(ip+"isipv6address");
-
}else{
-
System.out.println(ip+"isunrecongized");
- }
-
-
if(address.isReachable(5000)){
-
System.out.println("SUCCESS-ping"+IP+"withnointerfacespecified");
-
}else{
-
System.out.println("FAILURE-ping"+IP+"withnointerfacespecified");
- }
-
-
System.out.println("\n-------Tryingdifferentinterfaces--------\n");
-
- Enumeration<NetworkInterface>netInterfaces=
- NetworkInterface.getNetworkInterfaces();
-
while(netInterfaces.hasMoreElements()){
- NetworkInterfaceni=netInterfaces.nextElement();
- System.out.println(
-
"Checkinginterface,DisplayName:"+ni.getDisplayName()+",Name:"+ni.getName());
-
if(address.isReachable(ni,0,5000)){
-
System.out.println("SUCCESS-ping"+ip);
-
}else{
-
System.out.println("FAILURE-ping"+ip);
- }
-
- Enumeration<InetAddress>ips=ni.getInetAddresses();
-
while(ips.hasMoreElements()){
-
System.out.println("IP:"+ips.nextElement().getHostAddress());
- }
-
System.out.println("-------------------------------------------");
- }
-
}catch(Exceptione){
-
System.out.println("erroroccurs.");
- e.printStackTrace();
- }
- }
程序输出
- --------------START--------------
-
-
10.13.20.70isipv4address
-
SUCCESS-ping10.13.20.70withnointerfacespecified
-
- -------Tryingdifferentinterfaces--------
-
-
Checkinginterface,DisplayName:MSTCPLoopbackinterface,Name:lo
-
FAILURE-ping10.13.20.70
-
IP:127.0.0.1
- -------------------------------------------
-
Checkinginterface,DisplayName:Intel(R)Centrino(R)Advanced-N6200AGN-
- Teefer2Miniport,Name:eth0
-
FAILURE-ping10.13.20.70
-
IP:9.123.231.40
- -------------------------------------------
-
Checkinginterface,DisplayName:Intel(R)82577LMGigabitNetworkConnection-
- Teefer2Miniport,Name:eth1
-
SUCCESS-ping10.13.20.70
- -------------------------------------------
-
Checkinginterface,DisplayName:WAN(PPP/SLIP)Interface,Name:ppp0
-
SUCCESS-ping10.13.20.70
-
IP:10.0.50.189
- -------------------------------------------
-
- --------------END--------------
从上可以看出isReachable的用法,可以不指定任何接口来判断远端网络的可达性,但这不能区分出数据包是从那个网络接口发出去的 (如果本地有多个网络接口的话);而高级版本的isReachable则可以指定从本地的哪个网络接口测试,这样可以准确的知道远端网络可以连通本地的哪个网络接口。
但是,Java本身没有提供任何方法来判断本地的哪个IP地址可以连通远端网络,Java网络编程接口也没有提供方法来访问ICMP协议数据包,因而通过ICMP的网络不可达数据包实现这一点也是不可能的 (当然可以用JNI来实现,但就和系统平台相关了 ), 此时可以考虑本文下一节提出的方法。
指定本地和远程网络地址,判断两台机器之间的可达性
在某些情况下,我们可能要确定本地的哪个网络地址可以连通远程网络,以便远程网络可以回连到本地使用某些服务或发出某些通知。一个典型的应用场景是,本地启动了文件传输服务(如FTP),需要将本地的某个IP地址发送到远端机器,以便远端机器可以通过该地址下载文件;或者远端机器提供某些服务,在某些事件发生时通知注册了获取这些事件的机器 ( 常见于系统管理领域 ),因而在注册时需要提供本地的某个可达 (从远端) 地址。
虽然我们可以用InetAddress.isReachabl方法判断出本地的哪个网络接口可连通远程玩过,但是由于单个网络接口是可以配置多个IP地址的,因而在此并不合适。我们可以使用Socket建立可能的TCP连接,进而判断某个本地 IP 地址是否可达远程网络。我们使用java.net.Socket 类中的connect方法。
- voidconnect(SocketAddressendpoint,inttimeout)
这种方法需要远程的某个端口,该端口可以是任何基于TCP协议的开放服务的端口(如一般都会开放的ECHO服务端口7,Linux的SSH服务端口22等)。实际上,建立的TCP连接被协议栈放置在连接队列,进而分发到真正处理数据的各个应用服务,由于UDP没有连接的过程,因而基于UDP的服务(如 SNMP)无法在此方法中应用。
具体过程是,枚举本地的每个网络地址,建立本地Socket,在某个端口上尝试连接远程地址,如果可以连接上,则说明该本地地址可达远程网络。
程序清单2:指定本地地址和远程地址,判断两台机器之间的可达性
- voidprintReachableIP(InetAddressremoteAddr,intport){
-
StringretIP=null;
-
- Enumeration<NetworkInterface>netInterfaces;
-
try{
- netInterfaces=NetworkInterface.getNetworkInterfaces();
-
while(netInterfaces.hasMoreElements()){
- NetworkInterfaceni=netInterfaces.nextElement();
- Enumeration<InetAddress>localAddrs=ni.getInetAddresses();
-
while(localAddrs.hasMoreElements()){
- InetAddresslocalAddr=localAddrs.nextElement();
-
if(isReachable(localAddr,remoteAddr,port,5000)){
- retIP=localAddr.getHostAddress();
-
break;
- }
- }
- }
-
}catch(SocketExceptione){
- System.out.println(
-
"Erroroccurredwhilelistingallthelocalnetworkaddresses.");
- }
-
if(retIP==null){
-
System.out.println("NULLreachablelocalIPisfound!");
-
}else{
-
System.out.println("ReachablelocalIPisfound,itis"+retIP);
- }
- }
-
-
booleanisReachable(InetAddresslocalInetAddr,InetAddressremoteInetAddr,
-
intport,inttimeout){
-
-
booleanisReachable=false;
-
Socketsocket=null;
-
try{
- socket=newSocket();
-
-
SocketAddresslocalSocketAddr=newInetSocketAddress(localInetAddr,0);
- socket.bind(localSocketAddr);
- InetSocketAddressendpointSocketAddr=
-
newInetSocketAddress(remoteInetAddr,port);
- socket.connect(endpointSocketAddr,timeout);
-
System.out.println("SUCCESS-connectionestablished!Local:"+
-
localInetAddr.getHostAddress()+"remote:"+
-
remoteInetAddr.getHostAddress()+"port"+port);
-
isReachable=true;
-
}catch(IOExceptione){
-
System.out.println("FAILRE-CANnotconnect!Local:"+
-
localInetAddr.getHostAddress()+"remote:"+
-
remoteInetAddr.getHostAddress()+"port"+port);
-
}finally{
-
if(socket!=null){
-
try{
- socket.close();
-
}catch(IOExceptione){
-
System.out.println("Erroroccurredwhileclosingsocket..");
- }
- }
- }
-
returnisReachable;
- }
运行结果
- --------------START--------------
-
-
FAILRE-CANnotconnect!Local:127.0.0.1remote:10.8.1.50port22
-
FAILRE-CANnotconnect!Local:9.123.231.40remote:10.8.1.50port22
-
SUCCESS-connectionestablished!Local:10.0.50.189remote:10.8.1.50port22
-
ReachablelocalIPisfound,itis10.0.50.189
-
- --------------END--------------
IPv4和IPv6混合网络下编程
当网络环境中存在IPv4和IPv6,即机器既有IPv4地址,又有IPv6地址的时候,我们可以对程序进行一些优化,比如
- 由于IPv4和IPv6地址之间是无法互相访问的,因此仅需要判断IPv4地址之间和IPv6地址之间的可达性。
- 对于IPv4的换回地址可以不做判断,对于IPv6的Linklocal地址也可以跳过测试
- 根据实际的需要,我们可以优先考虑选择使用IPv4或者IPv6,提高判断的效率
程序清单3: 判断本地地址和远程地址是否同为IPv4或者IPv6
-
if(!((localInetAddrinstanceofInet4Address)&&(remoteInetAddrinstanceofInet4Address)
- ||(localInetAddrinstanceofInet6Address)&&(remoteInetAddrinstanceofInet6Address))){
-
-
break;
- }
程序清单4:跳过本地地址和LinkLocal地址
- if(localAddr.isLoopbackAddress()||
- localAddr.isAnyLocalAddress()||
- localAddr.isLinkLocalAddress()){
-
-
break;
- }
总结和展望
本文列举集中典型的场景,介绍了通过Java网络编程接口判断机器之间可达性的几种方式。在实际应用中,可以根据不同的需要选择相应的方法稍加修改即可。对于更加特殊的需求,还可以考虑通过JNI的方法直接调用系统API来实现,能提供更加强大和灵活的功能,这里就不再赘述了。
相关推荐
Java FTP、TCP、UDP、SMTP邮件验证与连接测试是网络编程中的重要环节,涉及...在实际应用中,理解这些协议的特性,选择合适的协议进行通信,以及编写有效的连通性测试代码,对于保证网络服务的稳定性和效率至关重要。
通过java 验证机器与某ip地址能否联通的工具类。配置ip地址就可以测试使用了。
动态连通性的应用广泛,为寻找出一种能够有效解决动态连通性问题的方法,本文基于Java语言对三种动态连通性算法进行实现和测试,通过对结果的分析,判断每种算法的运行时间及效率,选择出最为有效的解决动态连通性...
对于测试IP是否可达的功能,可以模拟不同网络条件,如连通的IP、不可达的IP、无效的IP,验证`isReachable()`方法的行为。 通过以上步骤,我们可以构建一个完整的Java工程,实现对IP地址的真实性和可达性的测试。在...
net-tools.jar是一个网络连通性测试工具包,启动需要jre 1.8及以上版本支持 启动方法: java -jar net-tools.jar 在提示中选择需要启动的模块: Please select start module(1.tcpserver,2.tcpclient, 3.udpserver,...
在安卓平台上,我们可以使用ping命令来进行网络连通性的监测。ping是一个简单但实用的网络诊断工具,通过发送ICMP(Internet Control Message Protocol)回显请求来检测网络连接的延迟和丢包情况。在应用中,我们...
java实现的简单网络管理协议!附件是整个工程,下载下来配置ip就可以运行,附有mib库,支持snmpV1,V2,V3版本协议!绝对是好资源,为了兼容移动的网络设备控制,研究了一段时间,现分享出来。不懂得可以找我
Ping是一个网络诊断工具,用于检查网络连通性。11-Ping-Channel使用Java NIO(非阻塞I/O)的DatagramChannel实现,而10-Ping-Datagram则使用了传统的Socket DatagramPacket。 6. **Eclipse IDE**:00-EclipseIDE...
支持单数据读写,多数据读写,大数据量自动分包读写 支持序列化批量多地址且地址不连续的读写 支持读取DB区,I区,Q区,M区,V区 支持读取西门子S1200,200Smart 支持PLC自动重连 ...
在IT领域,尤其是在软件开发与网络编程中,检查URL链接的连通性是常见的需求之一。这不仅有助于确保应用程序能够顺利地与外部服务交互,也是进行自动化测试、监控系统健康状态的重要手段。以下是对给定文件中“java...
首先启动虚拟机,然后通过`ifconfig`(在Linux中)或`ipconfig`(在Windows中)获取各自的IP地址,用`ping`测试网络连通性,确保渗透机(172.16.1.4)与靶机(172.16.1.12)之间可以通信。 接下来,对靶机上的JBoss...
在IT行业中,网络通信是至关重要的一个环节,而`PING`命令作为一种基本的网络诊断工具,被广泛用于检查网络连通性、测量网络延迟以及评估网络的稳定性。本篇文章将详细探讨`Java`中实现`PING`的综合测试,包括最大...
本文将深入解析两段Java代码,它们分别用于检查URL的连通性和可用性。 首先,我们来看第一段代码,这个方法`testWsdlConnection(String address)`用于测试一个给定的URL地址是否能正常连接: ```java public ...
在这个示例中,通过创建Socket实例并尝试连接到目标服务器,我们可以有效地检测服务的连通性。这在系统监控、故障排查和自动化流程中都非常有用。同时,理解异常处理和资源管理是编写健壮网络代码的关键。
批量测试IP地址的场景可能出现在网络管理员需要检查大量服务器或设备的网络连通性,或者在部署分布式系统时验证节点间的通信。 端口是网络通信中的逻辑通道,对应于特定服务或应用。TCP和UDP协议分别有65535个可用...