0

ポート 6789 でクラス C の IP アドレスに ping を実行するコードを書きましたPING。ポート 6789 が開いているすべての IP アドレスを取得します。しかし、私が必要としているのは、たとえば 5 秒ごとに更新 (再 ping) し、最近参加した IP が存在する場合は追加し、ポートを離れる IP を省略することです。残念ながら、別の問題が発生します。アプリケーションを起動すると、 の最初の反復がwhile (true)完全に機能し、ポート 6789 が開いている IP が に追加され、ArrayList ips_Listに表示されますListView。別のデバイスがポートに参加すると、私の電話はそれを に追加しますips_Listまた。しかし、スレッドが 5 秒間スリープした後の 2 回目の反復で、(xxx1 - xxx254) から IP への再 ping を開始して、以前に ping された IP への ping 時に別の IP がポートに参加したかどうかを確認すると、ソケットは 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に使用される...同じアプリを持つ2つのモバイルがあることを考慮して、PINGボタンをクリックすると、他のデバイスにpingが送信され、他のデバイスがaccept()接続close()されます。ここで、最初のモバイルでもう一度繰り返し ( while(true))、同じデバイスに ping を送信しますが、そのデバイスはServerSocket閉じているため、 が返されますfalse。これには再帰スレッドが使用され、モバイル 1 がモバイル 2 に ping を送信すると、モバイル 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 に答える