java关于ping方面的解惑
java在JDK1.5以前都是用java.nio包中的Ping类来实现ping。在JDK1.7版本的API文档中就没找到这个类了。
java.nio包是对非阻塞流IO进行处理,java.io包是对阻塞流IO进行处理。前几天都是使用io阻塞流来实现客户端与服务端的通信。
在socket中,目前我知道的有两个人方法可以阻塞程序,一个是输入流InputStream的read方法,一个是ServerSocket中的accept
方法。C/S模式中有个弊端,当客户端每次向服务端发送socket,服务端都会开启一个线程来管理,那么10000个客户端,服务端
就需要开启10000个线程,当客户端数量较大的时候,阻塞流IO显然不适合,那么就要使用非阻塞流IO,如果有10000个客户端,
服务端使用非阻塞IO流就只要1000个线程就可以完成管理,因为阻塞流IO是同步的,非阻塞流IO是异步的,更多的关于阻塞流IO
与非阻塞流IO的知识,我想我需要相关书籍进行学习。
那么JAVA实现ping,可以调用WINDOS系统下的命令符ping来实现。代码如下:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.UnknownHostException; public class Test { public static void ping(String host){ String line = null; try{ Process pro = Runtime.getRuntime().exec("ping " + host); BufferedReader buf = new BufferedReader(new InputStreamReader(pro.getInputStream(),"gbk")); while ((line = buf.readLine()) != null){ System.out.println(line); } }catch (Exception ex){ System.out.println(ex.getMessage()); } } /** * @param host */ public static void icmp(String host){ try { int timeOut = 3000; boolean status = InetAddress.getByName(host).isReachable(timeOut); System.out.println("发送数据包: " + status); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * @param args */ public static void main(String[] args) throws UnknownHostException { ping(InetAddress.getByName("www.baidu.com").getHostAddress()); icmp(InetAddress.getByName("www.baidu.com").getHostAddress()); } }
从代码中可以看出,我是ping了百度的,百度发回来的报文是GBK格式的,不设置会出现乱码现象,还有一个点是InetAddress包中的isReachable方法,这个方法在API文档中描述是这样的:
测试该地址是否可访问。最好的实现是通过尝试到达主机,但是防火墙和服务器配置可能会阻塞导致不可到达状态的请求,而某些特定端口可能是可访问的。一个典型的实现将使用ICMP回声请求,如果可以获得特权,否则它将试图在目标主机的端口7(回声)上建立一个TCP连接。
超时值(以毫秒为单位)表示尝试应该占用的最大时间。如果操作在获得答案之前超时,则主机被认为是不可到达的。负值将导致时抛出。
也就是说,这个方法基本上是使用目标主机的端口7建立TCP连接了,基本不关PING什么事情。
附上JDK1.5版本以前的Ping类实现,有兴趣的可以看看。
https://docs.oracle.com/javase/1.5.0/docs/guide/nio/example/index.html