如何用java编写程序实现发现某一网段内的活动主机

解决方案 »

  1.   

    Java 1.5以下没有对ICMP协议的支持,需要用JNI或NIO来完成,可以Google一下。如果用1.5以上版本,有一个简单的方法
    String host = "192.168.1.181"
    int timeOut = 3000;
    boolean status = InetAddress.getByName(host).isReachable(timeOut);
    InetAddress.isReachable()方法实现了ICMP,也就是Ping.(需要有一定的系统权限)
      

  2.   

    public static void main( String[] args )
    {
    StringBuffer buf = new StringBuffer();
    String s = "";
    Process process;
    try
    {
    process = Runtime.getRuntime().exec( "cmd /c " + "ping 127.0.0.1" );
    BufferedReader br = new BufferedReader( new InputStreamReader(
    process.getInputStream() ) );
    while ( ( s = br.readLine() ) != null )
    {
    buf.append( s + "\r\n" );
    } process.waitFor();
    System.out.println( buf );
    } catch ( Exception ex )
    {
    ex.printStackTrace();
    }
    }
      

  3.   

    在 JDK 的 Document 上有些 NIO 的例子,里面有个 Ping.java,有兴趣的话可以去看看:http://java.sun.com/j2se/1.5.0/docs/guide/nio/example/index.html
      

  4.   

    2楼的方法不推荐,因为是用runtime.exec来直接调用ping命令,系统平台改变时要改代码。其次没有必要用java重新写ping,大多说人关心的是用java来检测远程主机是否可用。我把这个写在blog里了。http://blog.csdn.net/cgaolei/archive/2009/06/04/4240835.aspx
      

  5.   

    答:其实cgaolei兄弟的理解有一点儿偏差。8楼火龙果的方案是正规的方案(也是JAVA DOC文档中的方案--当然是最权威的了)
    为什么说有偏差呢?是因为:在isReachable(timeOut);的代码实现中--目前其实在WINDOWS平台,并没有采用ICMP协议来完成,而是采用TCP的PORT 7来完成功能的。因而不是通常从们所讲的PING的程序。
    请看以下一段的说明:isReachable(timeOut);
    方法最终调用的是native c的实现代码中的Inet4AddressImpl_isReachable0(...)
    在该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     */
        fd = NET_Socket(AF_INET, SOCK_STREAM, 0);
        if (fd == JVM_IO_ERR) {
            /* note: if you run out of fds, you may not be able to load
             * the exception class, and get a NoClassDefFoundError
             * instead.
             */
            NET_ThrowNew(env, WSAGetLastError(), "Can't create socket");
            return JNI_FALSE;
        }
        if (ttl > 0) {
          setsockopt(fd, IPPROTO_IP, IP_TTL, (const char *)&ttl, sizeof(ttl));
        }
        /*
         * A network interface was specified, so let's bind to it.
         */
        if (netif != NULL) {
          if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
            NET_ThrowNew(env, WSAGetLastError(), "Can't bind socket");
            closesocket(fd);
            return JNI_FALSE;
          }
        }    /*
         * Make the socket non blocking so we can use select/poll.
         */
        hEvent = WSACreateEvent();
        WSAEventSelect(fd, hEvent, FD_READ|FD_CONNECT|FD_CLOSE);    /* no need to use NET_Connect as non-blocking */
        him.sin_port = htons(7);    /* Echo */    connect_rv = connect(fd, (struct sockaddr *)&him, len);    /**
         * connection established or refused immediately, either way it means
         * we were able to reach the host!
         */请看上边红色的部分,说明了native c的实现代码中其实是通过TCP向远方的PORT 7(即:ECHO服务)来达到“是否可达到”的功能的。目前并不是ICMP的实现。结论:
    当然还是按SUN公司的JAVA 文档中的权威例子,即8楼火龙果所给的连接中的例子(Ping.java)。
      

  6.   

    多谢11楼指教,的解没有注意到,因为只看到了API,没有看到底层实现。请问你给出的C代码对应的java版本是多少?谢谢
      

  7.   

    完全不懂你们在说什么。虽然学过一点JAVA不过这东西实在太高深。深受打击
      

  8.   


    感谢jiangnaisong的严谨态度,学习了。 看来官方API文档还不够全面,也不能完全相信。
      

  9.   

    刚好有个程序给你了,呵呵
    import java.io.*;public class Ping
    {
        public static void main(String args[])
        {
            String line = null;
            try
            {
                Process pro = Runtime.getRuntime().exec("ping 127.0.0.1 ");
                BufferedReader buf = new BufferedReader(new InputStreamReader(pro.getInputStream()));
                while ((line = buf.readLine()) != null)
                    System.out.println(line);
            }
            catch (Exception ex)
            {
                System.out.println(ex.getMessage());
            }
        }} 
      

  10.   


    我看了一下这个官方的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协议的三次握手原理,即使对方机器在端口上没有服务,当接收到请求时会立刻拒绝,如果对方机器不在网络上则结果是超时!这个方法的实现正是利用了这一点。总结:在使用java 1.5以上平台时,做用InetAddress.isReachable()方法是最佳的,推荐使用。
      

  11.   

    经过我在windows xp的平台下测试,23楼和8楼的情况都行不通。但是通过cmd的方式确实是可以的。
    大家考虑酌情使用!