`
cgaolei
  • 浏览: 57355 次
  • 性别: Icon_minigender_1
  • 来自: 长春
社区版块
存档分类
最新评论

用Java实现Ping的功能(续)

阅读更多

之前的文章中,我推荐使用InetAddress类中的isReachable()方法来实现ping的功能。不久后,就有网上的朋友对我的观点做出了指点。其指出的是isReachable方法在Windows系统平台上的实现(native c)并没有使用ICMP,而是全完使用连接echo端口7 的方法。

在OpenJDK 6 Windows平台上Native c的实现中有几段注释:

/*
 * Windows implementation of ICMP & RAW sockets is too unreliable for now.
 * Therefore it's best not to try it at all and rely only on TCP
 * We may revisit and enable this code in the future.
 */

/* Can't create a raw socket, so let's try a TCP socket */

him.sin_port = htons(7); /* Echo */ 
connect_rv = connect(fd, (struct sockaddr *)&him, len);

可以看到,在windows下isReachable方法的确是只使用了连接端口7的方法。这一点在API文档上并没有指出 。所以我对其理解存在偏差也就在此(没有去看具体的实现代码,也感谢指出我问题的朋友)。


网上还有另一种方法是使用官方关于NIO包的例子中的ping方法:
源代码URL:http://java.sun.com/j2se/1.5.0/docs/guide/nio/example/Ping.java

我看了一下这个官方的NIO ping的例子,并对其进行了调试和数据捕获。实际,这个官方的例子使用的方法并不是通过ICMP实现的,而是通过连接daytime端口13

// The default daytime port
static int DAYTIME_PORT = 13;
// The port we'll actually use
static int port = DAYTIME_PORT;

try {
        address = new InetSocketAddress(InetAddress.getByName(host),port);
} catch (IOException x) {
        failure = x;
}

我也在Linux下使用InetAddress.isReachable()方法做了试验:当登录为普通用户时,使用的是连接echo端口7,登录为root用户时,使用的是ICMP请求。通过对一台网络上的路由进行连接,两个测试结果都反回了true.


InetAddress.isReachable()通过试图连接TCP端口的方法是利用了TCP/IP协议的三次握手原理,即使对方机器在端口上没有服务,当接收到请求时会立刻拒绝,如果对方机器不在网络上则结果是超时!这个方法的实现正是利用了这一点。

引用OpenJDK 6,isReachable()方法native c实现的一段注释:

/**
 * connection established or refused immediately, either way it means
 * we were able to reach the host!
 */

 总结:在使用java 5以上版本开发时,无论哪种系统平台,使用InetAddress.isReachable()方法都是最佳的。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics