public class TestPing {
public static void main(String[] args) {
InetAddress address = null;
String ipStr="135.198.181.205";
try {
address = InetAddress.getByName(ipStr);
} catch (UnknownHostException e) {
e.printStackTrace();
}
System.out.println(address.getHostName());
System.out.println(address.getHostAddress());
final InetAddress tmpAddress = address;
try {
if (!tmpAddress.isReachable(10000)) {
System.out.println(address.getHostAddress()+" is not reachable");
}else{
System.out.println(address.getHostAddress()+" is reachable");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
The InetAddress.isReachable() return false in some servers, but if use the Ping command 'ping -n 1 -w 10000 135.198.181.205' in windows or 'ping -c 1 -w 10000 135.198.181.205' in linux, the ping result is true.
It is strange!
some one says that
Linux/Unix, instead, supports an ICMP "ping" system call. So the implementation of java.net.InetAddress.isReachable() first tries to perform the "ping" system call**; if this fails, itfalls back trying to open a TCP socket on [sic - to] port 7, as in Windows.
It turns out that in Linux/Unix the ping system call requires root privileges, so most of the times java.net.InetAddress.isReachable() will fail, because many Java programs are not run as root, and because the target address unlikely has the echo service up and running. Too bad.
Yes, when the program was executed in root privileges, it did return true. but the regular program is not executed in root. actually this is a bug, only the root privilege could send the ICMP packets, so while the program running on not root privilege and the port 7 is not available then the isReachable method would return false. To validate this thought, i run the TestPing program in the Windows, and the result still is false, while i run the TestPing program in the linux with the root privilege, the result is true. and this test proves that the Sending ICMP packets could be used by root, and the tcp sockets at port 7 failed, then the TestPing could be failed both on windows and linux.
so the next step is to find the cause while the tcp connection to port 7 in the remote server is failed.
then use the command 'netstat -tn |grep 7' to see whether the port 7 is occupied or not, and find none program is used.
And the isReachable method attempts Tcp-3 way handshake with Port 7(Echo) which is completely different from the ICMP Ping which sends ICMP Type 8 (ECHO) to the host and await an ICMP Type 0 (ECHO Reply). and if the server is not listening on port 7, so it returns false where as normal ping command receive reply as network link is up.
using /etc/init.d/iptables status to check whether the firewalls is stopped. if it is closed then it would print "FireWall is stopped".
command '/etc/init.d/iptables start' to start the firewalls, and command '/etc/init.d/iptables stop' to stop the firewalls.
But if i close the firewalls on the remote server using the command '/etc/init.d/iptables stop', then isReachable method return true. so the problem is the Port 7 is closed. if open the port 7, then this method could return true. and Why port 7 is closed? Because the destination is a ESX Server Vmware, and its default configuration is to close all the ports smaller than 3000 after the version vmware 3.0. so
IF not to close the firewall, should use the command "/sbin/iptables -A INPUT -p tcp --dport 7 -j ACCEPT" to open the Port 7, then the method isReachable() could return true;
and /sbin/iptables -L command could print the content of rules:
iptables -L
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere
valid-tcp-flags tcp -- anywhere anywhere
valid-source-address !udp -- anywhere anywhere
valid-source-address-udp udp -- anywhere anywhere
valid-source-address tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,ACK/SYN
icmp-in icmp -- anywhere anywhere
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ideafarm-chat state NEW
ACCEPT tcp -- anywhere anywhere tcp dpt:http state NEW
ACCEPT tcp -- anywhere anywhere tcp dpt:https state NEW
ACCEPT udp -- anywhere anywhere udp spts:bootps:bootpc dpts:bootps:bootpc
ACCEPT udp -- anywhere anywhere udp dpt:svrloc
ACCEPT tcp -- anywhere anywhere tcp dpt:svrloc state NEW
ACCEPT tcp -- anywhere anywhere tcp dpt:wbem-https state NEW
ACCEPT tcp -- anywhere anywhere tcp dpt:wbem-http state NEW
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh state NEW
ACCEPT tcp -- anywhere anywhere tcp dpts:av-emb-config:remote-collab state NEW
ACCEPT udp -- anywhere anywhere udp dpts:av-emb-config:remote-collab state NEW
ACCEPT tcp -- anywhere anywhere tcp dpts:8042:8045 state NEW
ACCEPT udp -- anywhere anywhere udp dpts:8042:8045 state NEW
ACCEPT tcp -- anywhere anywhere tcp dpt:echo <-端口已经添加
some tips:
netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息,这里我只用到其中的部分功能.
netstat 的常用参数: - t、- u、- w和- x分别表示TCP、UDP、RAW和UNIX套接字连接。-a标记,还会显示出等待连接(也就是说处于监听模式)的套接字。-l 显示正在被监听(listen)的端口, -n表示直接显示端口数字而不是通过察看/etc/service来转换为端口名,-p选项表示列出监听的程序
1) netstat -tl
查看当前tcp监听端口
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:rrac *:* LISTEN
tcp 0 0 *:34006 *:* LISTEN
......
2) netstat -tlp
查看当前tcp监听端口, 需要显示监听的程序名,当不清楚mysql的监听端口时比较好用
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 *:rrac *:* LISTEN -
tcp 0 0 *:34006 *:* LISTEN 23425/mysqld
......
3) netstat -tl | grep 34006
只查看mysql的监听端口,当前启动的mysql端口为34006,明确知道mysql监听端口时使用
4) netstat -ta | grep 34006
tcp 0 0 *:34006 *:* LISTEN
tcp 0 0 linux.local:34006 linux.local:41485 ESTABLISHED
tcp 0 0 linux.local:34006 linux.local:41486 ESTABLISHED
...
tcp 0 0 10.3.2.35:41488 10.3.2.35:34006 ESTABLISHED
tcp 0 0 10.3.2.35:41489 10.3.2.35:34006 ESTABLISHED
tcp 0 0 10.3.2.35:41490 10.3.2.35:34006 ESTABLISHED
由于数据库和运用程序都放在同一台机器了,因此这里连接被显示了两次. 可以使用-p参数来显示PID,然后grep PID.
5) netstat -tap | grep 34006 | grep 23425
23425是当前mysql的PID
tcp 0 0 *:34006 *:* LISTEN 23425/mysqld
tcp 0 0 linux.local:34006 linux.local:41510 ESTABLISHED 23425/mysqld
tcp 0 0 linux.local:34006 linux.local:41511 ESTABLISHED 23425/mysqld
tcp 0 0 linux.local:34006 linux.local:41516 ESTABLISHED 23425/mysqld
iptables:
using /etc/init.d/iptables status to check whether the firewalls is stopped. if it is closed then it would print "FireWall is stopped".
command '/etc/init.d/iptables start' to start the firewalls, and command '/etc/init.d/iptables stop' to stop the firewalls.
1) 重启后永久性生效: 开启: chkconfig iptables on 关闭: chkconfig iptables off
2) 即时生效,重启后失效:开启: service iptables start 关闭: service iptables stop
需要说明的是对于Linux下的其它服务都可以用以上命令执行开启和关闭操作。
在开启了防火墙时,做如下设置,开启相关端口,
修改/etc/sysconfig/iptables 文件,添加以下内容:
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT