无法ping两次相同的IP

时间:2013-05-01 14:15:36

标签: android multithreading sockets ping

我已编写此代码用于在端口6789上ping C类IP地址,当我单击名为PING的按钮时,该线程启动。它将检索端口6789打开的所有IP地址。但我需要的是刷新(重新ping)每个,比如5秒,并添加最近加入的IP(如果存在)并省略离开端口的IP。不幸的是,另一个问当我启动应用程序时,while (true)的第一次迭代完美地工作,它将任何端口6789打开的IP添加到ArrayList ips_List,然后将其显示在ListView上,并在另一台设备加入端口,我的手机也会将其添加到ips_List。但是在线程休眠5秒之后的第二次迭代中,然后开始从(xxx1 - xxx254)重新ping IP以查看在ping到之前ping的IP时是否有另一个IP加入了端口,Socket将抛出IOException (如代码所示)。

为什么会这样?

Thread pingo = new Thread(new Runnable() {
            public void run() {
                while (true) {

                    if (readableNetmask.equals("255.255.255.0")) {

                        for (int i = 2; i <= 25; i++) {

                            String ip_address = readableIPAddress;
                            String oct1 = "", oct2 = "", oct3 = "", oct4 = "";

                            StringTokenizer stok = new StringTokenizer(
                                    ip_address, ".");

                            while (stok.hasMoreTokens()) {
                                oct1 = stok.nextToken();
                                oct2 = stok.nextToken();
                                oct3 = stok.nextToken();
                                oct4 = stok.nextToken();
                            }

                            to_ping_ip = oct1 + "." + oct2 + "." + oct3
                                    + "." + String.valueOf(i);

                            if (pingAddress(to_ping_ip, 6789)) {
                                ips_List.add(to_ping_ip);
                            }
                        }
                    }


                    // delay 10 seconds, then re-ping
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        break;
                    }
                    handler.post(new UpdateIPListViewRunnable());
                }
            }
        });
        pingo.start();

PingAddress()函数:

public boolean pingAddress(String ip, int port) {

   Socket socket = new Socket();
   try {

      socket.connect(new InetSocketAddress(ip, port), 200);
      socket.close();

   } catch (IOException e) {
       return false;
   }
   return true;
   }

列出地址的位置:

static public class UpdateIPListViewRunnable implements Runnable {
    public void run() {
        arrayAdapter.clear();
        for (int i = 0; i < ips_List.size(); i++) {
            arrayAdapter.add(ips_List.get(i));
            arrayAdapter.notifyDataSetChanged();
        }
        ips_List.clear();
    }
}

2 个答案:

答案 0 :(得分:1)

您的问题很可能出在“ping”这个词的非典型用法上。传统上,这是指发送ICMP回应请求,该请求不涉及连接状态,但通常也不允许普通用户ID,例如您的应用程序将在其下运行。

您似乎正在使用有状态TCP连接,如果您的服务器未经过调整以便能够接受快速重新连接,则可能会遇到困难。因此,您可能希望尝试使用其他客户端测试您的服务器。您可能还有一个问题,即TCP将继续尝试通过流量,因此它不会快速报告网络故障。您甚至可能最终会多次尝试重叠。

你最好的解决办法可能是从不适合这项任务的TCP切换到UDP,这可能是一个更好的匹配。 UDP没有连接状态,并且它也不可靠,因为没有尝试自动重试。您应该能够通过Web搜索找到UDB echo服务器和客户端类型示例。

答案 1 :(得分:0)

谢谢@Chris Stratton ......现在我正在改变协议到UDP,因为我的项目结构是在TCP架构上构建的......现在我的问题终于找到了解决方案;在我的应用程序中,我有ServerSocket用于ping ...现在考虑有两个移动设备使用相同的应用程序,如果单击PING按钮,则它将ping另一个设备,而另一个设备将{{1然后连接accept()。现在,在第一个移动设备上,它会迭代另一个时间(close())并ping同一设备,但该设备已关闭while(true),因此它将返回ServerSocket。因为这是一个递归线程,当移动1 ping移动2时,移动2将关闭false并立即调用相同的线程,以便ServerSocket打开其他ping。我尝试了它并且效果很好:DDD

[@专家:此解决方案的任何增强功能!]

递归线程:

ServerSocket