【问题标题】:How to Ping External IP from Java Android如何从 Java Android ping 外部 IP
【发布时间】:2011-04-23 18:02:14
【问题描述】:

我正在为 Android 2.2 开发一个 Ping 应用程序。

我尝试了我的代码,它可以工作,但仅在本地 IP 中,这是我的问题,我也想对外部服务器执行 ping 操作。

这是我的代码:

  private OnClickListener milistener = new OnClickListener() {
    public void onClick(View v) {
        TextView info = (TextView) findViewById(R.id.info);
        EditText edit = (EditText) findViewById(R.id.edit);
        Editable host = edit.getText();
        InetAddress in;
        in = null;
        // Definimos la ip de la cual haremos el ping
        try {
            in = InetAddress.getByName(host.toString());
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // Definimos un tiempo en el cual ha de responder
        try {
            if (in.isReachable(5000)) {
                info.setText("Responde OK");
            } else {
                info.setText("No responde: Time out");
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            info.setText(e.toString());
        }
    }
};

Ping 127.0.0.1 -> 好的
Ping 8.8.8.8 (Google DNS) -> 超时

我也在 Manifest XML 中添加了以下行:

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

谁能建议我哪里做错了?

【问题讨论】:

  • 还有更多信息^^你是在模拟器还是真机上测试?您是否启用了互联网连接?即在真实设备上确保“移动网络”已激活并且您有互联网连接
  • 我在模拟器和连接到互联网的真实设备上进行了测试。谢谢。
  • 这个问题你做对了吗?我有同样的问题。如果你解决了这个问题,你能否给我一些建议。问候桑杰
  • 我也遇到了同样的问题,如果你发现了请提供解决方案!
  • 到了这个链接,我得到了答案,stackoverflow.com/questions/14576710/…

标签: java android


【解决方案1】:

我尝试了以下代码,这对我有用。

private boolean executeCommand(){
        System.out.println("executeCommand");
        Runtime runtime = Runtime.getRuntime();
        try
        {
            Process  mIpAddrProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
            int mExitValue = mIpAddrProcess.waitFor();
            System.out.println(" mExitValue "+mExitValue);
            if(mExitValue==0){
                return true;
            }else{
                return false;
            }
        }
        catch (InterruptedException ignore)
        {
            ignore.printStackTrace();
            System.out.println(" Exception:"+ignore);
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
            System.out.println(" Exception:"+e);
        }
        return false;
    }

【讨论】:

  • 我发现这是在 4.1 上检查 ICMP 回显的唯一可靠方法。
  • 您需要特殊权限才能运行它吗?
  • 有人能解释一下吗?检查“mExitValue”如何确保 ping 成功?
  • 检查命令的退出值很有用,因为退出 0 通常意味着命令成功。任何其他值都表明存在问题。
  • 这在投入使用时会泄漏内存并递归调用它!您需要手动关闭标准输入、标准输出和标准错误文件描述符。 runtime.getInputStream().close(); runtime.getOutputStream().close(); runtime.getErrorStream().close();使用此命令检查管道泄漏:adb shell ls -l /proc//fd。请编辑答案并添加流关闭,我在这种预期的行为上崩溃了好几天..
【解决方案2】:

这是我在其中一个项目中使用的简单 ping:

public static class Ping {
    public String net = "NO_CONNECTION";
    public String host = "";
    public String ip = "";
    public int dns = Integer.MAX_VALUE;
    public int cnt = Integer.MAX_VALUE;
}

public static Ping ping(URL url, Context ctx) {
    Ping r = new Ping();
    if (isNetworkConnected(ctx)) {
        r.net = getNetworkType(ctx);
        try {
            String hostAddress;
            long start = System.currentTimeMillis();
            hostAddress = InetAddress.getByName(url.getHost()).getHostAddress();
            long dnsResolved = System.currentTimeMillis();
            Socket socket = new Socket(hostAddress, url.getPort());
            socket.close();
            long probeFinish = System.currentTimeMillis();
            r.dns = (int) (dnsResolved - start);
            r.cnt = (int) (probeFinish - dnsResolved);
            r.host = url.getHost();
            r.ip = hostAddress;
        }
        catch (Exception ex) {
            Timber.e("Unable to ping");
        }
    }
    return r;
}

public static boolean isNetworkConnected(Context context) {
    ConnectivityManager cm =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}

@Nullable
public static String getNetworkType(Context context) {
    ConnectivityManager cm =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (activeNetwork != null) {
        return activeNetwork.getTypeName();
    }
    return null;
}

用法:ping(new URL("https://www.google.com:443/"), this);

结果:{"cnt":100,"dns":109,"host":"www.google.com","ip":"212.188.10.114","net":"WIFI"}

【讨论】:

  • 这会 ping 特定端口,而其他解决方案使用 ICMP ping(不是特定端口)。所以这是一个有趣的选择。我猜,不需要root权限?
  • 不需要root访问权限,但&lt;uses-permission android:name="android.permission.INTERNET" /&gt;应该在清单中。
【解决方案3】:

在 Android 的命令中运行 ping 实用程序并解析输出(假设您有 root 权限)

参见下面的Java代码sn-p:

executeCmd("ping -c 1 -w 1 google.com", false);

public static String executeCmd(String cmd, boolean sudo){
    try {

        Process p;
        if(!sudo)
            p= Runtime.getRuntime().exec(cmd);
        else{
            p= Runtime.getRuntime().exec(new String[]{"su", "-c", cmd});
        }
        BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));

        String s;
        String res = "";
        while ((s = stdInput.readLine()) != null) {
            res += s + "\n";
        }
        p.destroy();
        return res;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "";

}

【讨论】:

  • 我正在执行 ping -c 10(平均 10 个 ping)是否可以逐行显示?我尝试让它将 s 附加到 TextView ,它通常会将 s 附加到 res 但没有奏效。
【解决方案4】:

在我的情况下,ping 可以从设备运行,但不能从模拟器运行。我找到了这个文档: http://developer.android.com/guide/developing/devices/emulator.html#emulatornetworking

关于“本地网络限制”的主题它说:

"根据环境不同,模拟器可能无法支持 其他协议(例如 ICMP,用于“ping”)可能不是 支持的。目前,模拟器不支持 IGMP 或 多播。”

更多信息: http://groups.google.com/group/android-developers/browse_thread/thread/8657506be6819297

这是 QEMU 用户模式网络堆栈的已知限制。 引用原始文档:请注意,不支持 ping 可靠地连接到 Internet,因为它需要 root 权限。它 意味着您只能ping本地路由器(10.0.2.2)。

【讨论】:

    【解决方案5】:

    Ping 谷歌服务器或任何其他服务器

    public boolean isConecctedToInternet() {
    
        Runtime runtime = Runtime.getRuntime();
        try {
            Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
            int     exitValue = ipProcess.waitFor();
            return (exitValue == 0);
        } catch (IOException e)          { e.printStackTrace(); }
        catch (InterruptedException e) { e.printStackTrace(); }
        return false;
    }
    

    【讨论】:

    • 这段代码适用于哪个版本的android?它可以在android 4.1+上运行吗
    • 这不是一个通用的解决方案,因为它依赖于外部实用程序。
    【解决方案6】:

    我在纯 Android Java 中实现了“ping”并将其托管在 gitlab 上。它与 ping 可执行文件做同样的事情,但更容易配置。它有几个有用的功能,比如能够绑定到给定的网络。

    https://github.com/dburckh/AndroidPing

    【讨论】:

      【解决方案7】:

      这是我自己实现的,它返回平均延迟:

      /*
      Returns the latency to a given server in mili-seconds by issuing a ping command.
      system will issue NUMBER_OF_PACKTETS ICMP Echo Request packet each having size of 56 bytes
      every second, and returns the avg latency of them.
      Returns 0 when there is no connection
       */
      public double getLatency(String ipAddress){
          String pingCommand = "/system/bin/ping -c " + NUMBER_OF_PACKTETS + " " + ipAddress;
          String inputLine = "";
          double avgRtt = 0;
      
          try {
              // execute the command on the environment interface
              Process process = Runtime.getRuntime().exec(pingCommand);
              // gets the input stream to get the output of the executed command
              BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
      
              inputLine = bufferedReader.readLine();
              while ((inputLine != null)) {
                  if (inputLine.length() > 0 && inputLine.contains("avg")) {  // when we get to the last line of executed ping command
                      break;
                  }
                  inputLine = bufferedReader.readLine();
              }
          }
          catch (IOException e){
              Log.v(DEBUG_TAG, "getLatency: EXCEPTION");
              e.printStackTrace();
          }
      
          // Extracting the average round trip time from the inputLine string
          String afterEqual = inputLine.substring(inputLine.indexOf("="), inputLine.length()).trim();
          String afterFirstSlash = afterEqual.substring(afterEqual.indexOf('/') + 1, afterEqual.length()).trim();
          String strAvgRtt = afterFirstSlash.substring(0, afterFirstSlash.indexOf('/'));
          avgRtt = Double.valueOf(strAvgRtt);
      
          return avgRtt;
      }
      

      【讨论】:

        【解决方案8】:

        您的(移动)提供商可能阻止了 ICMP 数据包。如果此代码在模拟器上不起作用,请尝试通过 wireshark 或任何其他嗅探器进行嗅探,并在触发 isReachable() 方法时查看线路上发生了什么。

        您还可以在设备日志中找到一些信息。

        【讨论】:

        • 我已经在通过 Wifi 连接的 Android 2.2 平板电脑上进行了测试,我不使用任何 Momile 提供商。谢谢。
        • 那么你的下一步应该是嗅探你的设备产生的流量(不是)。这里有很多可能出错的地方......
        • 这不太可能是由 ICMP 阻塞引起的,因为 Android 文档说 InetAddress.isReachable 首先尝试通过 ICMP 进行 ping,如果失败,它会尝试在 TCP 端口 7 (Echo) 上进行 ping 操作
        • 根据android.git.kernel.org/?p=platform/libcore.git;a=blob;f=luni/…如果不指定接口将不会使用ICMP。 isReachable 仅使用 TCP Echo 的东西,似乎是一些奇怪的行为或防火墙问题或其他什么......你确定你能够从你的应用程序访问互联网吗?曾经尝试过通过 HTTP 接收文件吗?
        • 如何测试我的应用可以访问互联网??
        【解决方案9】:

        获取ip上命中的布尔值

        public Boolean getInetAddressByName(String name)
            {
                AsyncTask<String, Void, Boolean> task = new AsyncTask<String, Void, Boolean>()
                {
        
                    @Override
                    protected Boolean doInBackground(String... params) {
                        try
                        {
                            return InetAddress.getByName(params[0]).isReachable(2000);
                        }
                        catch (Exception e)
                        {
                            return null;
                        }
                    }
                };
                try {
                    return task.execute(name).get();
                }
                catch (InterruptedException e) {
                    return null;
                }
                catch (ExecutionException e) {
                    return null;
                }
        
            }
        

        【讨论】:

          【解决方案10】:

          使用此代码:此方法适用于 4.3+,也适用于以下版本。

             try {
          
                   Process process = null;
          
                  if(Build.VERSION.SDK_INT <= 16) {
                      // shiny APIS 
                         process = Runtime.getRuntime().exec(
                              "/system/bin/ping -w 1 -c 1 " + url);
          
          
                  } 
                  else 
                  {
          
                             process = new ProcessBuilder()
                           .command("/system/bin/ping", url)
                           .redirectErrorStream(true)
                           .start();
          
                      }
          
          
          
                  BufferedReader reader = new BufferedReader(new InputStreamReader(
                          process.getInputStream()));
          
                  StringBuffer output = new StringBuffer();
                  String temp;
          
                  while ( (temp = reader.readLine()) != null)//.read(buffer)) > 0)
                  {
                      output.append(temp);
                      count++;
                  }
          
                  reader.close();
          
          
                  if(count > 0)
                      str = output.toString();
          
                  process.destroy();
               } catch (IOException e) {
                   e.printStackTrace();
              }
          
              Log.i("PING Count", ""+count);
              Log.i("PING String", str);
          

          【讨论】:

            【解决方案11】:

            粉色IP地址

              public static int pingHost(String host, int timeout) throws IOException,
                    InterruptedException {
                Runtime runtime = Runtime.getRuntime();
                timeout /= 1000;
                String cmd = "ping -c 1 -W " + timeout + " " + host;
                Process proc = runtime.exec(cmd);
                Log.d(TAG, cmd);
                proc.waitFor();
                int exit = proc.exitValue();
                return exit;
            }
               Ping a host and return an int value of 0 or 1 or 2 0=success, 1=fail,
               * 2=error
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-06-16
              • 1970-01-01
              • 2019-10-17
              • 2020-11-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多