Generally, we only need to determine whether one machine can access (Ping) another machine. At this time, we can simply use the java.net.InetAddress class in the Java class library to achieve this. This class provides There are two methods to detect whether the remote machine is reachable
boolean isReachable(int timeout) // 测试地址是否可达 boolean isReachable(NetworkInterface netif, int ttl, int timeout) // 测试地址是否可达.
To put it simply, the above method is to construct the InetAddress object through the IP address of the remote machine, and then call its isReachable method to test the network between the calling machine and the remote machine. Accessibility. Note that the remote machine may have multiple IP addresses, so you may want to iteratively test all scenarios.
void isAddressAvailable(String ip){ try{ InetAddress address = InetAddress.getByName(ip);//ping this IP if(address instanceof java.net.Inet4Address){ System.out.println(ip + " is ipv4 address"); }else if(address instanceof java.net.Inet6Address){ System.out.println(ip + " is ipv6 address"); }else{ System.out.println(ip + " is unrecongized"); } if(address.isReachable(5000)){ System.out.println("SUCCESS - ping " + IP + " with no interface specified"); }else{ System.out.println("FAILURE - ping " + IP + " with no interface specified"); } System.out.println("\n-------Trying different interfaces--------\n"); Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces(); while(netInterfaces.hasMoreElements()) { NetworkInterface ni = netInterfaces.nextElement(); System.out.println( "Checking interface, 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(Exception e){ System.out.println("error occurs."); e.printStackTrace(); } }
Program output:
--------------START-------------- 10.13.20.70 is ipv4 address SUCCESS - ping 10.13.20.70 with no interface specified -------Trying different interfaces-------- Checking interface, DisplayName:MS TCP Loopback interface, Name:lo FAILURE - ping 10.13.20.70 IP: 127.0.0.1 ------------------------------------------- Checking interface, DisplayName:Intel(R) Centrino(R) Advanced-N 6200 AGN - Teefer2 Miniport, Name:eth0 FAILURE - ping 10.13.20.70 IP: 9.123.231.40 ------------------------------------------- Checking interface, DisplayName:Intel(R) 82577LM Gigabit Network Connection - Teefer2 Miniport, Name:eth2 SUCCESS - ping 10.13.20.70 ------------------------------------------- Checking interface, DisplayName:WAN (PPP/SLIP) Interface, Name:ppp0 SUCCESS - ping 10.13.20.70 IP: 10.0.50.189 ------------------------------------------- --------------END--------------
As you can see from the above, the usage of isReachable can be used to determine the reachability of the remote network without specifying any interface, but this cannot distinguish where the data packet comes from. Which network interface is sent out (if there are multiple local network interfaces); and the advanced version of isReachable can specify which local network interface to test from, so that you can accurately know which local network interface the remote network can connect to.
However, Java itself does not provide any method to determine which local IP address can connect to the remote network, and the Java network programming interface does not provide a method to access ICMP protocol data packets, so the network through ICMP is unreachable. It is also impossible to implement this through the package (of course it can be achieved using JNI, but it depends on the system platform). At this time, you can consider the method proposed in the next section of this article.
In some cases, we may want to determine which local network address can connect to the remote network, so that the remote network can connect back to the local to use certain services or issue certain notifications. A typical application scenario is that a file transfer service (such as FTP) is started locally, and a local IP address needs to be sent to the remote machine so that the remote machine can download files through this address; or the remote machine provides certain The service notifies the machine registered to obtain these events when certain events occur (common in the field of system management), so a local reachable (from the remote) address needs to be provided when registering.
Although we can use the InetAddress.isReachabl method to determine which local network interface can be connected to remote play, it is not suitable here because a single network interface can be configured with multiple IP addresses. We can use Socket to establish a possible TCP connection and then determine whether a local IP address is reachable to the remote network. We use the connect method in the java.net.Socket class
void connect(SocketAddress endpoint, int timeout) //使用Socket连接服务器,指定超时的时间
This method requires a remote port, which can be the port of any open service based on the TCP protocol (such as the generally open ECHO service Port 7, Linux SSH service port 22, etc.). In fact, the established TCP connection is placed in the connection queue by the protocol stack and then distributed to various application services that actually process the data. Since UDP does not have a connection process, UDP-based services (such as SNMP) cannot be applied in this method.
The specific process is to enumerate each local network address, establish a local Socket, and try to connect to the remote address on a certain port. If it can be connected, it means that the local address can reach the remote network.
void printReachableIP(InetAddress remoteAddr, int port){ String retIP = null; Enumeration<NetworkInterface> netInterfaces; try{ netInterfaces = NetworkInterface.getNetworkInterfaces(); while(netInterfaces.hasMoreElements()) { NetworkInterface ni = netInterfaces.nextElement(); Enumeration<InetAddress> localAddrs = ni.getInetAddresses(); while(localAddrs.hasMoreElements()){ InetAddress localAddr = localAddrs.nextElement(); if(isReachable(localAddr, remoteAddr, port, 5000)){ retIP = localAddr.getHostAddress(); break; } } } } catch(SocketException e) { System.out.println( "Error occurred while listing all the local network addresses."); } if(retIP == null){ System.out.println("NULL reachable local IP is found!"); }else{ System.out.println("Reachable local IP is found, it is " + retIP); } } boolean isReachable(InetAddress localInetAddr, InetAddress remoteInetAddr, int port, int timeout) { booleanisReachable = false; Socket socket = null; try{ socket = newSocket(); // 端口号设置为 0 表示在本地挑选一个可用端口进行连接 SocketAddress localSocketAddr = new InetSocketAddress(localInetAddr, 0); socket.bind(localSocketAddr); InetSocketAddress endpointSocketAddr = new InetSocketAddress(remoteInetAddr, port); socket.connect(endpointSocketAddr, timeout); System.out.println("SUCCESS - connection established! Local: " + localInetAddr.getHostAddress() + " remote: " + remoteInetAddr.getHostAddress() + " port" + port); isReachable = true; } catch(IOException e) { System.out.println("FAILRE - CAN not connect! Local: " + localInetAddr.getHostAddress() + " remote: " + remoteInetAddr.getHostAddress() + " port" + port); } finally{ if(socket != null) { try{ socket.close(); } catch(IOException e) { System.out.println("Error occurred while closing socket.."); } } } return isReachable; }
Running results
--------------START-------------- FAILRE - CAN not connect! Local: 127.0.0.1 remote: 10.8.1.50 port22 FAILRE - CAN not connect! Local: 9.123.231.40 remote: 10.8.1.50 port22 SUCCESS - connection established! Local: 10.0.50.189 remote: 10.8.1.50 port22 Reachable local IP is found, it is 10.0.50.189 --------------END--------------
When there are IPv4 and IPv6 in the network environment, that is, when the machine has both an IPv4 address and an IPv6 address, we can make some optimizations to the program, such as
Since IPv4 and IPv6 addresses cannot access each other, it is only necessary to determine the reachability between IPv4 addresses and between IPv6 addresses.
You don’t need to judge the IPv4 return address, and you can skip the test for the IPv6 Linklocal address
According to actual needs, We can give priority to using IPv4 or IPv6 to improve the efficiency of judgment
Judge whether the local address and remote address are both IPv4 or IPv6
// 判断是 IPv4 还是 IPv6 if(!((localInetAddr instanceofInet4Address) && (remoteInetAddr instanceofInet4Address) || (localInetAddr instanceofInet6Address) && (remoteInetAddr instanceofInet6Address))){ // 本地和远程不是同时是 IPv4 或者 IPv6,跳过这种情况,不作检测 break; }
Skip the local address and LinkLocal Address
if( localAddr.isLoopbackAddress() || localAddr.isAnyLocalAddress() || localAddr.isLinkLocalAddress() ){ // 地址为本地环回地址,跳过 break; }
The above is the detailed content of How to test Java network connectivity. For more information, please follow other related articles on the PHP Chinese website!