安卓中的Ping应用程序

12

1
https://dev59.com/EGs05IYBdhLWcg3wGuKd#7452375 - Mohammed Azharuddin Shaikh
你对你提供的链接有什么具体的问题?你尝试过什么? - 323go
1
你需要 ping 的哪些“特性”? - Simon
往返时延,数据包丢失计算。 - user1944616
3个回答

23

我已经使用以下代码进行ping测试。

public String ping(String url) {
    String str = "";
    try {
        Process process = Runtime.getRuntime().exec(
                "/system/bin/ping -c 8 " + url);
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                process.getInputStream()));
        int i;
        char[] buffer = new char[4096];
        StringBuffer output = new StringBuffer();
        while ((i = reader.read(buffer)) > 0)
            output.append(buffer, 0, i);
        reader.close();

        // body.append(output.toString()+"\n");
        str = output.toString();
        // Log.d(TAG, str);
    } catch (IOException e) {
        // body.append("Error\n");
        e.printStackTrace();
    }
    return str;
}

在这个URL中,您需要传递要ping的地址。


非常有帮助...我的一半工作已经完成了...但我仍然不明白如何格式化输出?你有什么建议吗? - user1944616
你知道怎么格式化输出吗?这样会更有帮助……先谢谢了。我不知道要用哪个库。 - user1944616
你说的“如何格式化输出”是什么意思?你想要对它做什么具体的操作? - Sahil Mahajan Mj
在输出中,所有内容都一起打印出来,我想像这样打印它(每个内容都在新行中): [ip地址] [数据包序列号] [TTL] [RTT] - user1944616
我刚试图在按钮点击上调用此函数 public void pingTheServer(View view){ txtStatus.setText(ping("http://www.blueleaftech.in")); } 但无法显示返回的字符串,我已经设置了使用网络权限。 - Prasanth A R

14
感谢您研究此问题。您链接的问题(以及SO上的许多其他问题)都指向使用系统的ping可执行文件或尝试可疑的InetAddress.isReachable方法的解决方案。但是,如果您愿意添加一些本地代码,还有第三种选择
我最近为Android VPN应用程序实现了ICMP Echo(ping)功能。我无法使用系统“ping”可执行文件,因为它发送的ICMP数据包被我的VPN捕获,而且无论如何,我想能够将ICMP数据包从我的网络转发到外部世界并接收回复。
InetAddress.isReachable方法对我根本没有用(始终返回false),这在SO上已经被彻底讨论过,例如herehere

我想分享一种解决方案,就是使用本地代码创建一个ICMP套接字。我利用这个套接字发送和接收ICMP数据包(也就是用于“ping”的回显请求和响应)。自2011年以来,Linux内核支持创建不需要特殊权限的ICMP套接字。新的ICMP套接字作为一个数据报套接字被创建,协议类型为PROT_ICMP。这里有一个很好的C语言实现示例,可在this answer中查看。

ICMP套接字功能也已经被移植到了Android平台,并且甚至被用于"ping"程序中。实际上,有人建议它可以用来修复InetAddress.isReachable()的实现

Java API不支持此功能,但使用本地代码可以打开ICMP套接字。我使用JNA访问所需的libC函数(socket()、close()、sendto()、recvfrom()、poll()等)。我想JNI也可以同样适用。

为了绕过VPN限制,需要使用VpnService.protect(int)来保护套接字文件描述符。

LWN文章 所述,有一些需要注意的地方:

  • 请确保您的系统允许 ICMP sockets,可以通过读取(并可能设置)“/proc/sys/net/ipv4/ping_group_range”文件的内容进行确认。
  • 内核会修改 ICMP 头中的“identifier”字段,如果您打算将回复数据包转发给原始请求者,则必须重置它(并重新计算校验和)。

如何使用基于Java的VpnService.protect()方法保护在本地代码中创建的套接字?例如,您是否必须将来自本地代码的fd返回到Java中,然后使用它调用protect()?此外,如果ping_group_range显示为“0 2147483647”,这是否意味着它已启用所有内容? - LBC
1
我自己回答了这个问题:是的,只需从本地代码返回fd,并将int直接传递到VpnService.protect()中。保护后,现在能够接收ICMP响应。 - LBC

2
我使用纯Android Java实现了“ping”,并将其托管在gitlab上。它有一些有用的功能,比如能够绑定到给定的网络。 https://github.com/dburckh/AndroidPing 翻译成:GitHub链接:https://github.com/dburckh/AndroidPing

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接