资讯专栏INFORMATION COLUMN

Java 实现 Ping 命令

lastSeries / 2765人阅读

摘要:是和系统下的一个命令。也属于一个通信协议,是协议的一部分。利用命令可以检查网络是否连通。百度百科上关于的介绍写的还不错,可以参考。做这个是因为我们需要用程序下载一些资源,先提前简单判断一下是否可连通,有需要的随便拿去。

Ping是Windows、Unix和Linux系统下的一个命令。Ping也属于一个通信协议,是TCP/IP协议的一部分。利用 ping 命令可以检查网络是否连通。

百度百科上关于 Ping 的介绍写的还不错,可以参考。

尝试用Java 写了个简易的实现,代码如下:

package com.coder4j.main;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.regex.Pattern;

/**
 * Java 实现的简易Ping 工具
 * 
 * @author Chinaxiang
 * @date 2015-08-11
 *
 */
public class JavaPing {

    private static int port = 80;

    /**
     * 内部Target 类,一个实例代表一个Socket 连接
     */
    private static class Target {
        private InetSocketAddress address;
        private SocketChannel channel;
        private Exception failure;
        private long connectStart;
        private long connectFinish = 0;
        private boolean shown = false;

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

        public void show() {
            String result;
            if (connectFinish != 0) {
                result = Long.toString(connectFinish - connectStart) + "ms";
            } else if (failure != null) {
                result = failure.toString();
            } else {
                result = "Timed out";
            }
            System.out.println(address + " : " + result);
            shown = true;
        }
    }

    /**
     * 内部Printer 类,继承自Thread ,实现对Target实例show方法的调用
     */
    private static class Printer extends Thread {
        private LinkedList pending = new LinkedList();

        public Printer() {
            setName("Printer");
            setDaemon(true);
        }

        public void add(Target t) {
            synchronized (pending) {
                pending.add(t);
                pending.notify();
            }
        }

        public void run() {
            try {
                for (;;) {
                    Target t = null;
                    synchronized (pending) {
                        while (pending.size() == 0) {
                            pending.wait();
                        }
                        t = pending.removeFirst();
                    }
                    t.show();
                }
            } catch (InterruptedException x) {
                return;
            }
        }
    }

    /**
     * 内部Connector 类,继承自Thread ,实现对Target 列表的Ping 测试
     */
    private static class Connector extends Thread {
        private Selector sel;
        private Printer printer;
        private LinkedList pending = new LinkedList();

        public Connector(Printer pr) throws IOException {
            printer = pr;
            sel = Selector.open();
            setName("Connector");
        }

        public void add(Target t) {
            SocketChannel sc = null;
            try {
                sc = SocketChannel.open();
                sc.configureBlocking(false);
                boolean connected = sc.connect(t.address);
                t.channel = sc;
                t.connectStart = System.currentTimeMillis();
                if (connected) {
                    t.connectFinish = t.connectStart;
                    sc.close();
                    printer.add(t);
                } else {
                    synchronized (pending) {
                        pending.add(t);
                    }
                    sel.wakeup();
                }
            } catch (IOException x) {
                if (sc != null) {
                    try {
                        sc.close();
                    } catch (IOException xx) {
                    }
                }
                t.failure = x;
                printer.add(t);
            }
        }

        private void processPendingTargets() throws IOException {
            synchronized (pending) {
                while (pending.size() > 0) {
                    Target t = pending.removeFirst();
                    try {
                        t.channel.register(sel, SelectionKey.OP_CONNECT, t);
                    } catch (IOException x) {
                        t.channel.close();
                        t.failure = x;
                        printer.add(t);
                    }
                }
            }
        }

        private void processSelectedKeys() throws IOException {
            for (Iterator i = sel.selectedKeys().iterator(); i.hasNext();) {
                SelectionKey sk = i.next();
                i.remove();
                Target t = (Target) sk.attachment();
                SocketChannel sc = (SocketChannel) sk.channel();
                try {
                    if (sc.finishConnect()) {
                        sk.cancel();
                        t.connectFinish = System.currentTimeMillis();
                        sc.close();
                        printer.add(t);
                    }
                } catch (IOException x) {
                    sc.close();
                    t.failure = x;
                    printer.add(t);
                }
            }
        }

        volatile boolean shutdown = false;

        public void shutdown() {
            shutdown = true;
            sel.wakeup();
        }

        public void run() {
            for (;;) {
                try {
                    int n = sel.select();
                    if (n > 0)
                        processSelectedKeys();
                    processPendingTargets();
                    if (shutdown) {
                        sel.close();
                        return;
                    }
                } catch (IOException x) {
                    x.printStackTrace();
                }
            }
        }
    }

    /**
     * 提供对外的ping 方法,调用示例:
* JavaPing.ping(new String[]{"www.baidu.com"});
* JavaPing.ping(new String[]{"80", "www.baidu.com"});
* JavaPing.ping(new String[]{"80", "www.baidu.com", "www.cctv.com"}); * * @param args * @throws IOException * @throws InterruptedException */ public static void ping(String[] args) throws IOException, InterruptedException { if (args.length < 1) { System.err.println("Usage: [port] host..."); return; } int firstArg = 0; if (Pattern.matches("[0-9]+", args[0])) { port = Integer.parseInt(args[0]); firstArg = 1; } Printer printer = new Printer(); printer.start(); Connector connector = new Connector(printer); connector.start(); LinkedList targets = new LinkedList(); for (int i = firstArg; i < args.length; i++) { Target t = new Target(args[i]); targets.add(t); connector.add(t); } Thread.sleep(2000); connector.shutdown(); connector.join(); for (Iterator i = targets.iterator(); i.hasNext();) { Target t = i.next(); if (!t.shown) { t.show(); } } } /** * 非常简易的ping方法,仅仅为了判断是否可连通。 * * @param host * @param port * @return */ public static boolean ping(String host, int port) { InetSocketAddress address = null; try { address = new InetSocketAddress(InetAddress.getByName(host), port); return !address.isUnresolved(); } catch (IOException e) { return false; } } public static void main(String[] args) throws InterruptedException, IOException { String[] arg = { "80", "www.baidu.com", "127.0.0.1", "www.cctv.com" }; JavaPing.ping(arg); // /127.0.0.1:80 : 2ms // www.baidu.com/61.135.169.121:80 : 5ms // www.cctv.com/220.194.200.232:80 : 14ms boolean result = JavaPing.ping("www.baidu.com", 80); System.out.println(result);// true } }

做这个是因为我们需要用程序下载一些资源,先提前简单判断一下是否可连通,有需要的随便拿去。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65429.html

相关文章

  • 开源一个监控数据采集Agent:OpenFalcon-SuitAgent

    摘要:目前此系统仅支持类系统下使用,不支持系统什么是这是一个获取各种系统的监控数据的。监控数据上报公有的跟官方社区的思想一致采集的系统监控信息如内存等等一百多种没有任何信息其他的业务系统的监控都会打上。 OpenFalcon-SuitAgent 项目地址:github 版本说明 本系统版本划分如下 alpha:内部测试版(不建议使用于生产环境) beta:公开测试版(不建议使用于生产环境)...

    linkin 评论0 收藏0
  • 开源一个监控数据采集Agent:OpenFalcon-SuitAgent

    摘要:目前此系统仅支持类系统下使用,不支持系统什么是这是一个获取各种系统的监控数据的。监控数据上报公有的跟官方社区的思想一致采集的系统监控信息如内存等等一百多种没有任何信息其他的业务系统的监控都会打上。 OpenFalcon-SuitAgent 项目地址:github 版本说明 本系统版本划分如下 alpha:内部测试版(不建议使用于生产环境) beta:公开测试版(不建议使用于生产环境)...

    王晗 评论0 收藏0

发表评论

0条评论

lastSeries

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<