如何在 Android 上进行 icmp ping

问题描述 投票:0回答:5

我需要从我的 Android 设备对主机执行 icmp ping。我需要测量往返时间。我精通android和java,只是不知道该使用什么库。 我该怎么做? 可以通过 3G、Edge 吗?

android icmp
5个回答
15
投票

是的,只要有连接,您就可以通过 3G、边缘、无线等方式进行 ping 操作。唯一的限制是模拟器,请参见此处: http://groups.google.com/group/android-developers/browse_thread/thread/8657506be6819297

这是我的 ping 函数:

package com.namespace.router.api;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import android.util.Log;

public class Network {

    private static final String TAG = "Network.java";   

    public static String pingError = null;

    /**
     * Ping a host and return an int value of 0 or 1 or 2 0=success, 1=fail, 2=error
     * 
     * Does not work in Android emulator and also delay by '1' second if host not pingable
     * In the Android emulator only ping to 127.0.0.1 works
     * 
     * @param String host in dotted IP address format
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    public static int pingHost(String host) throws IOException, InterruptedException {
        Runtime runtime = Runtime.getRuntime();
        Process proc = runtime.exec("ping -c 1 " + host);
        proc.waitFor();     
        int exit = proc.exitValue();
        return exit;
    }

    public static String ping(String host) throws IOException, InterruptedException {
        StringBuffer echo = new StringBuffer();
        Runtime runtime = Runtime.getRuntime();
        Log.v(TAG, "About to ping using runtime.exec");
        Process proc = runtime.exec("ping -c 1 " + host);
        proc.waitFor();
        int exit = proc.exitValue();
        if (exit == 0) {
            InputStreamReader reader = new InputStreamReader(proc.getInputStream());
            BufferedReader buffer = new BufferedReader(reader);
            String line = "";
            while ((line = buffer.readLine()) != null) {
                echo.append(line + "\n");
            }           
            return getPingStats(echo.toString());   
        } else if (exit == 1) {
            pingError = "failed, exit = 1";
            return null;            
        } else {
            pingError = "error, exit = 2";
            return null;    
        }       
    }

    /**
     * getPingStats interprets the text result of a Linux ping command
     * 
     * Set pingError on error and return null
     * 
     * http://en.wikipedia.org/wiki/Ping
     * 
     * PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
     * 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.251 ms
     * 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.294 ms
     * 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.295 ms
     * 64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.300 ms
     *
     * --- 127.0.0.1 ping statistics ---
     * 4 packets transmitted, 4 received, 0% packet loss, time 0ms
     * rtt min/avg/max/mdev = 0.251/0.285/0.300/0.019 ms
     * 
     * PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
     * 
     * --- 192.168.0.2 ping statistics ---
     * 1 packets transmitted, 0 received, 100% packet loss, time 0ms
     *
     * # ping 321321.
     * ping: unknown host 321321.
     * 
     * 1. Check if output contains 0% packet loss : Branch to success -> Get stats
     * 2. Check if output contains 100% packet loss : Branch to fail -> No stats
     * 3. Check if output contains 25% packet loss : Branch to partial success -> Get stats
     * 4. Check if output contains "unknown host"
     * 
     * @param s
     */
    public static String getPingStats(String s) {
        if (s.contains("0% packet loss")) {
            int start = s.indexOf("/mdev = ");
            int end = s.indexOf(" ms\n", start);
            s = s.substring(start + 8, end);            
            String stats[] = s.split("/");
            return stats[2];
        } else if (s.contains("100% packet loss")) {
            pingError = "100% packet loss";
            return null;            
        } else if (s.contains("% packet loss")) {
            pingError = "partial packet loss";
            return null;
        } else if (s.contains("unknown host")) {
            pingError = "unknown host";
            return null;
        } else {
            pingError = "unknown error in getPingStats";
            return null;
        }       
    }
}

6
投票

您可能想要使用

isReachable
- 请参阅 Android 文档 中的更多详细信息。然而,显然有些网络会阻止 ICMP。您可以在here阅读有关此问题的更多信息。


1
投票

您可以使用终端模拟器的开源代码这里

构建库(使用cygwinandroid-ndk)文件,然后使用


0
投票

icmp4a 库(我的库)使测量 ICMP 往返时间变得容易。此外,它不涉及通过

ping
或 Android NDK 执行
Runtime.exec()
命令。它是用纯 kotlin 编写的。

示例:

  1. 获取图书馆
implementation "com.marsounjan:icmp4a:1.0.0"
  1. 单个 ICMP Ping
val icmp = Icmp4a()
val host = "google.com"
try {
  val status = icmp.ping( host = "8.8.8.8")
  val result = status.result
  when (result) {
    is Icmp.PingResult.Success -> Log.d("ICMP", "$host(${status.ip.hostAddress}) ${result.packetSize} bytes - ${result.ms} ms")
    is Icmp.PingResult.Failed -> Log.d("ICMP", "$host(${status.ip.hostAddress}) Failed: ${result.message}")
  }
} catch (error: Icmp.Error.UnknownHost) {
  Log.d("ICMP", "Unknown host $host")
}

Logcat 输出

2024-01-26 16:22:48.515 ICMP D  google.com(8.8.8.8) 64 bytes - 12 ms
  1. 指定间隔的多个 ICMP Ping
val icmp = Icmp4a()
val host = "google.com"
try {
  icmp.pingInterval(
      "8.8.8.8",
      count = 5,
      intervalMillis = 1000
  )
    .onEach { status ->
        val result = status.result
        when (result) {
          is Icmp.PingResult.Success -> Log.d("ICMP", "$host(${status.ip.hostAddress}) ${result.packetSize} bytes - ${result.ms} ms")
          is Icmp.PingResult.Failed -> Log.d("ICMP", "$host(${status.ip.hostAddress}) Failed: ${result.message}")
        }
    }
      .launchIn(viewModelScope)
} catch (error: Icmp.Error.UnknownHost) {
  Log.d("ICMP", "Unknown host $host")
}

Logcat 输出

2024-01-26 16:29:16.633 ICMP D  google.com(8.8.8.8) 64 bytes - 15 ms
2024-01-26 16:29:17.577 ICMP D  google.com(8.8.8.8) 64 bytes - 17 ms
2024-01-26 16:29:18.598 ICMP D  google.com(8.8.8.8) 64 bytes - 17 ms
2024-01-26 16:29:19.614 ICMP D  google.com(8.8.8.8) 64 bytes - 15 ms
2024-01-26 16:29:20.630 ICMP D  google.com(8.8.8.8) 64 bytes - 13 ms

-1
投票

从 socket(2) 手册页来看,设备中的 ping 访问受到 /proc/sys/net/ipv4/ping_group_range 文件内容的限制

$ cat /proc/sys/net/ipv4/ping_group_range

默认为“1 0”,意思是 没有人(甚至 root 也不能)可以创建 ping 套接字。将其设置为“100 100" 将向单个组授予权限(使 /sbin/ping g+s 并归该组所有或授予权限 “netadmins”组),“0 4294967295”将为全世界启用它,“100 4294967295”将为用户启用它,但不会为守护进程启用它。

因此除“0 4294967295”之外的任何设备都无法从 Android java 应用程序访问

在模拟器中您可以测试是否重置

sysctl -w net.ipv4.ping_group_range="0 0" // 到某个范围

© www.soinside.com 2019 - 2024. All rights reserved.