2

現在、UDP メッセージをマルチキャスト グループに送信するデバイスがあります。グループに参加して適切なポートを探すことで、これらのパケットを検出できる小さな Java プログラムを作成しました。私はMulticastSocket.receive(packet);指図。この目的のために、GUI を使用したプログラムの作成に進みます。ユーザーが時間を指定できるようにし、プログラムがこの時間のパケットを検索できるようにしたいと考えています。多くの調査を行った結果、ポートをブロックしているときに受信コマンドを切断する最善の方法は、ポートを時期尚早に閉じることであることがわかりました。これを行うには、プログラムで別のスレッドを開き、新しいスレッドを使用して、メイン スレッドが指定された時間スリープしている間に UDP パケットを監視します。パケットを問題なく検出しています。ただし、メインスレッドからアクセスしてポートを閉じることはできないようです。これが私のコードです:

import java.io.*;

import java.net.*;

import java.util.*;

import javax.swing.*;

public class MulticastClient_v2 extends Thread
    {

    public volatile MulticastSocket socket; 

    public void run()
    {
        try {
            //Declare the port and IGMP Group IP
            MulticastSocket socket2 = new MulticastSocket(5000);
            InetAddress address = InetAddress.getByName("224.0.1.2");

            //Display connection information
            System.out.println("Joining 224.0.1.2 on port 5000");

            //Join the Multicast Group
            socket.joinGroup(address);

            //Declaring a DatagramPacket
            DatagramPacket packet;

            //Starting an infinite loop
            //while (true)
            //{
                System.out.println("Waiting on packets..");
                byte[] buf = new byte[1024];
                packet = new DatagramPacket(buf, buf.length); //Declaring an internal DatagramPacket
                socket.receive(packet); //Receiving a Packet

                String received = new String(packet.getData(), 0, packet.getLength());
                InetAddress senderAddress = packet.getAddress(); //Get the InetAddress object
                String forFun = senderAddress.getHostAddress(); //Extract the IP address of sender in text format
                if (received.indexOf("Product1") >= 0) //Searching the raw data for "Product1"
                {
                    //If found, display the IP and device type
                    System.out.println("Product1 found at " + senderAddress);

                }
                if (received.indexOf("Product2") >= 0) //Searching the raw data for "Product2"
                {
                    //If found, display the IP and device type
                    System.out.println("Product2 found at " + senderAddress);
                }

            //}
        }
        catch(IOException ex)
        {
            System.out.println (ex.toString());
        }
    }

    public static void main(String[] args)
    {   
        MulticastClient_v2 thread = new MulticastClient_v2();
        thread.start();
        try {
        Thread.sleep( 3000 );
        thread.socket2.close();
        }
        catch(InterruptedException in)
        {
            System.out.println("Interrupted Exception!");
        }
        System.out.println("Done.");
    }
}

そのため、コンパイルしようとすると、次のエラーが発生します。

MulticastClient_v2.java:63: error: cannot find symbol
    thread.socket2.close();
          ^
symbol:   variable socket2

メインメソッドがsocket2を見ることができず、別のメソッドにあるように思えます。私の質問は、それを表示できるようにする方法です。私は少し実験しました

public volatile MulticastSocket socket;

メインメソッドはそれにアクセスできますが、実行メソッドにいるときに特定のポートに接続できません。これを行うことができる唯一のものは bind() です。ただし、bind() には IP とポートの両方が必要ですが、最初にマルチキャスト ソケットを宣言するときは、次のようにポートだけを宣言できます。

MulticastSocket socket2 = new MulticastSocket(5000);

どんな助けでも大歓迎です!私はこれでしばらく立ち往生しています。

編集:私はいくつかの提案を得ました。まず、クラス レベルで宣言して初期化する必要があります。これにより、次の IO エラーが発生します。

MulticastClient_v2.java:8: error: unreported exception IOException; must be caught
or declared to be thrown
public volatile MulticastSocket socket = new MulticastSocket(5000); 
                                         ^

次に、クラス レベルで try..catch ブロックに入れてみたところ、次のようになりました。

MulticastClient_v2.java:8: error: illegal start of type
try{
^

したがって、JTMon が提案したように、クラス レベルでマルチキャスト ポートを初期化し、それをメソッド内の try ブロックに配置する必要があると思います。しかし、初期化中にそれを行わずにポートだけを選択する方法がわかりません。

編集 2: まだ問題があります。クラスレベルでそのように初期化しようとすると:

public volatile MulticastSocket socket;

後で run() メソッドでそのポートを編集するにはどうすればよいですか?

4

3 に答える 3

0

私が何を意味したかを正確に説明するために、ここにいくつかのコードを入れようとします。クラス レベルで変数 socket2 を宣言します。

MulticastClient_v2 クラスには、次の型のパブリック コンストラクターが必要です。

public MulticastClient_v2(int portNumber){
    try{
        socket2 = new MulticastSocket(portNumber);
    }catch(IOException e){
        //Do something with exception here
    }
}

ポート番号が変更されない場合はハード コードできますが、この方法の方が柔軟性があります。run メソッドでは、初期化されたソケットを使用できるようになり、クラスの外部から引き続きアクセスできます。記録のために、スレッドの別のメソッドを介してアクセスすることをお勧めしますが、それは別のスレッドの議論になるかもしれません;)

于 2012-07-31T09:20:13.770 に答える
0

socket2はローカル変数なので、スコープはtryそれが定義されているブロックだけです。インスタンスを使用するMulticastClient_v2と、そのクラスのフィールドにしかアクセスできませんでした。

于 2012-07-23T14:06:31.110 に答える
0

run メソッド内で socket2 がローカル変数として宣言されていませんか? そのメソッド以外の場所からはアクセスできません。最初にクラス レベルで宣言してみて、何が起こるかを確認してください。

于 2012-07-23T14:07:39.047 に答える