Android 利用ping命令判断当前网络状态

打印 上一主题 下一主题

主题 668|帖子 668|积分 2004

一. 介绍

        ping命令是用来测试和诊断网络连接问题的基本命令,当然我们的终端装备(手机/平板/车机)都可以用这个命令来判断当前网络是否有流量的状态,本篇文章主要介绍Linux的ping命令,因为Android系统也是利用了Linux内核。然后利用ping命令封装一个判断当前网络是否有流量的方法。

二. 作用

利用ping命令作用:
1. 检测网络连接问题:如果我们无法访问某个网站或主机,可以利用ping命令来检测网络连接是否正常。如果ping命令可以或许成功收到目标主机的回复,说明网络连接正常;如果无法收到回复,可能是网络故障或目标主机不可达。
2. 丈量网络延迟:通过ping命令可以丈量网络延迟,即从发送ICMP(Internet Control Message Protocol)(Internet控制消息协议)哀求到接收到回复所需的时间。可以利用ping命令的-c选项指定发送的ICMP哀求次数,然后盘算匀称延迟时间。较高的延迟可能会导致网络连接迟钝,需要进一步排查网络问题。
3. 检测丢包率:ping命令还可以用于检测网络丢包率,即发送的ICMP哀求在传输过程中丢失的比例。可以观察ping命令的输出结果中的丢包率字段,如果丢包率较高,可能是网络拥堵或目标主机负载过高。

三. 利用格式

  1. ping [参数] [主机名或IP地址]
复制代码
ping命令运行在命令提示符终端,用法为:“ping 参数 目标主机”。此中参数为零到多个,目标主机可以是IP大概域名。
如下图:

ping命令它会一连不停地给目标IP发送ICMP数据报,上面的截图中的每一行代表了一个从ICMP相应的信息,具体包括:
icmp_seq:ICMP 数据包序号,从1开始递增,如果中心不一连代表丢包了。
ttl:生存时间,具体指允许数据包之间通过多少个路由器或跳数,数据包每颠末一个路由器,ttl会减1,当ttl归零时,这个数据包的生成周期竣事,处理它的路由器会丢弃这个数据包。默认情况下,Linux系统的TTL值为64或255。
time: 这个数据报的相应时间,时间越短,代表相应速度越快。
然后是统计信息,它告诉我们,一共有12个数据报被通报,全被接收,没有数据包丢失。最后一行是:最小/最大/匀称相应时间和本机硬件泯灭时间。
看下所有的参数:
  1. ping -help
  2. Usage: ping [-aAbBdDfhLnOqrRUvV64] [-c count] [-i interval] [-I interface]
  3.             [-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos]
  4.             [-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option]
  5.             [-w deadline] [-W timeout] [hop1 ...] destination
  6. Usage: ping -6 [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface]
  7.              [-l preload] [-m mark] [-M pmtudisc_option]
  8.              [-N nodeinfo_option] [-p pattern] [-Q tclass] [-s packetsize]
  9.              [-S sndbuf] [-t ttl] [-T timestamp_option] [-w deadline]
  10.              [-W timeout] destination
复制代码
好了,到这里,我们来介绍一下它的参数:
参数详解
-aAudible ping. 
-A自适应ping,根据ping包来回时间确定ping的速度;
-c countping指定次数后停止ping;
-i interval设定间隔几秒发送一个ping包,默认一秒ping一次;
-I interface指定网卡接口、或指定的本机地址送出数据包;
-l preload设置在送出要求信息之前,先行发出的数据包;
-q不显示任何传送封包的信息,只显示最后的结果
-Q tos设置Qos(Quality of Service),它是ICMP数据报相关位;可以是十进制或十六进制数,详见rfc1349和rfc2474文档;
-R记载ping的路由过程(IPv4 only);
注意:由于IP头的限制,最多只能记载9个路由,其他会被忽略;
-s packetsize指定每次ping发送的数据字节数,默认为“56字节”+“28字节”的ICMP头,一共是84字节;
包头+内容不能大于65535,以是最大值为65507(linux:65507, windows:65500);
-t ttl设置TTL(Time To Live)为指定的值。该字段指定IP包被路由器丢弃之前允许通过的最大网段数;
-T timestamp_option 设置IP timestamp选项,可以是下面的任何一个:
'tsonly' (only timestamps)
'tsandaddr' (timestamps and addresses)
'tsprespec host1 [host2 [host3]]' (timestamp prespecified hops).
-v使ping处于verbose方式,它要ping命令除了打印ECHO-RESPONSE数据包之外,还打印其它所有返回的ICMP数据包;
-W timeout以毫秒为单元设置ping的超时时间;
-w deadlinedeadline;  单元 秒
其实常用的就是如下几个:
ping常用命令选项:
-c count:指定发送的ICMP哀求次数,默认为无限次。
-i interval:指定发送ICMP哀求的时间间隔,默认为1秒。
-s packetsize:指定发送的ICMP哀求的数据包巨细,默认为56字节。
-W timeout:指定等待ICMP回复的超时时间,默认为10秒。
-w 10   : 最长超时时间为10秒


四. 现实利用

利用ping命令访问阿里公共DNS,来判断当前网络是否有流量,间接的判断当前网络是否可用,目前国内公共的DNS有:
服务商公共DNS服务器IP公共DNS服务器IP
阿里DNS223.5.5.5223.6.6.6
114公共DNS114.114.114.114
百度DNS180.76.76.76
腾讯DNS119.29.29.29
电信101.226.4.6
联通123.125.81.6
移动101.226.4.6
谷歌8.8.8.88.8.4.4
IBM Quad9DNS9.9.9.9
微软DNS4.2.2.1
华为DNS139.9.23.90122.112.208.1
114.115.192.11116.205.5.1
代码如下:
  1. public boolean isNetworkHasTraffic() {
  2.         Runtime runtime = Runtime.getRuntime();
  3.         java.lang.Process ipProcess = null;
  4.         try {
  5.             ipProcess = runtime.exec("ping -c 4 -i 0.2 -w 1 223.5.5.5");
  6.             InputStream inputStrem = ipProcess.getInputStream();
  7.             BufferedReader in = new BufferedReader(new InputStreamReader(inputStrem));
  8.             StringBuffer stringBuffer = new StringBuffer();
  9.             String content = "";
  10.             while ((content = in.readLine()) != null) {
  11.                 stringBuffer.append(content);
  12.             }
  13.             int exitValue = ipProcess.waitFor();
  14.             Log.i(TAG, "return result after executing the ping command: " + exitValue);
  15.             if (exitValue == 0) {
  16.                 //网络正常且有流量
  17.                 return true;
  18.             } else if (exitValue == 1) {
  19.                 if (stringBuffer.indexOf("100% packet loss") != -1) {
  20.                     //状态值返回1 网络丢包严重,判断为网络未连接
  21.                     return false;
  22.                 } else {
  23.                     return true;
  24.                 }
  25.             } else if (exitValue == 2) {
  26.                 // 状态值返回2  网络未连接不可用
  27.                 return false;
  28.             } else {
  29.                 // 其他异常场景
  30.                 return false;
  31.             }
  32.         } catch(IOException | InterruptedException e) {
  33.             e.printStackTrace();
  34.         } finally {
  35.             if (ipProcess != null) {
  36.                 ipProcess.destroy();
  37.             }
  38.             runtime.gc();
  39.         }
  40.         return false;
  41.     }
复制代码
该方法中的ping 命令:
  1. ping -c 4 -i 0.2 -w 1 223.5.5.5
复制代码
发送4次数据, 每次间隔200毫秒,deadline 为1秒执行完成   
233.5.5.5 为阿里DNS
  1. ping -c 4 -i 0.2 -w 1 223.5.5.5
  2. PING 223.5.5.5 (223.5.5.5) 56(84) bytes of data.
  3. 64 bytes from 223.5.5.5: icmp_seq=1 ttl=114 time=87.7 ms
  4. 64 bytes from 223.5.5.5: icmp_seq=2 ttl=114 time=71.0 ms
  5. 64 bytes from 223.5.5.5: icmp_seq=3 ttl=114 time=72.2 ms
  6. 64 bytes from 223.5.5.5: icmp_seq=4 ttl=114 time=71.0 ms
  7. --- 223.5.5.5 ping statistics ---
  8. 4 packets transmitted, 4 received, 0% packet loss, time 601ms
  9. rtt min/avg/max/mdev = 71.007/75.506/87.732/7.084 ms
复制代码
返回值是通过调用 Process.waitFor() 方法,根据现实测试用例场景
1. 打开和关闭 手机流量开关  当正常上网时,返回值为0   关闭流量开关: 返回值2 
2. 连接上有流量的Wifi热门,正常上网时,返回值为0
3. 连接上没有流量的Wifi热门, 无法上网,返回值为1 ,此时丢包率是100%

五. 注意事项

java中 Process的waitFor() 方法说明
JDK帮助文档上这么说:如有必要,一直要等到由该 Process 对象表现的进程已经停止。如果已停止该子进程,此方法立即返回。但是直接调用这个方法会导致当前线程壅闭,直到退出子进程。
也就是说: 此方法不发起利用在主线程中,因为ping网络的过程是一个耗时操作,Process的waitFor()方法会壅闭当前线程 直接导致结果: 壅闭UI线程。
        颠末现实测试,确实会影响主线程,验证过程: 我把这个方法写在生命周期onStart()方法中,onResume() 就会延时1秒执行。那么UI界面也会延时1秒显示,这对用户寻求系统流畅角度来看,这当然是不允许的。
        当然waitFor()方法除了 0/1/2 尚有许多返回值,详细见:Process.waitFor()方法的返回值
 
六. 方法封装

在第5末节,我们已经说明此方法不发起利用在主线程中,下面是封装的方法和利用代码
利用方法一:
  1. new Thread(new Runnable() {
  2.             @Override
  3.             public void run() {
  4.                boolean isAvalible =  isNetworkHasTraffic();
  5.                //根据这个判断条件去处理对应的业务逻辑
  6.                if (isAvalible) {
  7.                    Log.d(TAG, " 网络正常 ");
  8.                } else {
  9.                    Log.d(TAG, " 当前网络不可用 ");
  10.                }
  11.             }
  12.         }).start();
复制代码
        
利用方法二:利用AsyncTask,把耗时操作放在doInBackground方法中,在子线程中做ping操作,当结果返回时,在onPostExecute主线程中更新状态。
  1. /*
  2.      Params:决定了执行excute()方法时传入的参数类型,excute()方法传入的参数会传入到方法doInBackground(),所以同时也决定了doInBackground()方法内的参数类型。
  3.      Progress:任务执行时,返回进度值的类型,即onProgressUpdate()方法内的参数类型。
  4.      Result:任务完成后,返回的结果的类型,即doInBackground()方法的返回类型,doInBackground()方法的返回结果传入onPostExecute()方法作为参数,所以同时也决定了onPostExecute()方法的参数类型。
  5.     *
  6.     * */
  7.     private abstract class getNetworkStatusTask extends AsyncTask<Void,Void,Boolean> {
  8.         @Override
  9.         protected Boolean doInBackground(Void... voids) {
  10.            return isNetworkHasTraffic();
  11.         }
  12.         //定义为抽象方法,在子类复写
  13.         @Override
  14.         protected abstract void onPostExecute(Boolean aBoolean);
  15.     }
  16. //调用代码
  17.    new getNetworkStatusTask(){
  18.                 @Override
  19.                 protected void onPostExecute(Boolean hastraffic) {
  20.                     //根据判断条件处理业务逻辑代码
  21.                     if (hastraffic) {
  22.                         Log.d(TAG, "====网络正常=====");
  23.                     } else {
  24.                         Log.d(TAG, "====网络不可用=====");
  25.                     }
  26.                 }
  27.             }.execute();
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

杀鸡焉用牛刀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表