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<Target> pending = new LinkedList<Target>();
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<Target> pending = new LinkedList<Target>();
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<SelectionKey> 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 方法,调用示例:<br>
* <code>JavaPing.ping(new String[]{"www.baidu.com"});</code><br>
* <code>JavaPing.ping(new String[]{"80", "www.baidu.com"});</code><br>
* <code>JavaPing.ping(new String[]{"80", "www.baidu.com", "www.cctv.com"});</code>
*
* @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<Target> targets = new LinkedList<Target>();
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<Target> 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
}
}
做这个是因为我们需要用程序下载一些资源,先提前简单判断一下是否可连通,有需要的随便拿去。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。