0

我编写了这段代码用于在端口 6789 上 ping C 类 IP 地址,当我单击一个名为PING. 它将检索所有打开端口 6789 的 IP 地址。但我需要的是每隔 5 秒刷新一次(重新 ping 一次),并添加最近加入的 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();
    }
}
4

2 回答 2

1

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

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

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

于 2013-05-01T16:35:14.253 回答
0

谢谢@Chris Stratton ...由于我的项目结构是基于TCP架构构建的,因此我无法将协议更改为UDP ...现在对于我的问题,我终于找到了解决方案;在我的应用程序中,我有一个ServerSocket用于 ping 的设备……现在考虑到有两部手机具有相同的应用程序,如果单击 PING 按钮,它将 ping 另一台设备,然后另一台设备将accept()连接close()它。现在在第一台移动设备上,它将再次迭代 ( while(true)) 并 ping 同一个设备,但该设备已ServerSocket关闭,因此它将返回false。为此使用了一个递归线程,当移动设备 1 ping 移动设备 2 时,移动设备 2 将关闭ServerSocket并立即调用同一线程,因此ServerSocket对其他 ping 开放。我试过了,效果很好:DDD

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

递归线程:

static public class ReceivePingThread extends Thread {
    public void run() {
        try {
            ServerSocket joinPort = new ServerSocket(6789, 100);
            joinPort.accept();
            joinPort.close();
            ReceivePingThread ReceivePingThread = new ReceivePingThread();
            ReceivePingThread.start();
        } catch (IOException e) {

            e.printStackTrace();
        }
    }
}
于 2013-05-01T18:17:46.030 回答