2012-07-23 46 views
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; 

和主要方法可以訪問它,但我無法連接到某端口,當我在run方法很。我唯一能找到的就是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{ 
^ 

所以,我想我真正需要做的是在類級別初始化播端口,然後把它放在一個方法內部try塊,作爲JTMon建議。但我無法想出一種方法來在初始化期間僅僅選擇其端口。編號2: 我還有困難。如果我嘗試在類級別初始化它:

public volatile MulticastSocket socket; 

如何在run()方法中稍後編輯其端口?

回答

0

socket2是一個局部變量,所以它的作用域就是它所在的try塊。使用MulticastClient_v2實例,您只能訪問該類的字段。

+0

已經嘗試在類級別聲明它,但它會引發IOException。所以我試圖把它放在一個「try..throw」中,但它說我必須在一個方法中做到這一點。 – user1546011 2012-07-23 14:13:00

+0

將其聲明爲字段並在構造函數中初始化它 – tibtof 2012-07-23 14:14:50

+0

在類級別聲明變量,並在方法內的try catch中使用它,然後發佈IO錯誤詳細信息,然後我們將再次嘗試解決它.....或其他人會;) – JTMon 2012-07-23 14:15:00

0

是不是將socket2聲明爲run方法內的局部變量?從該方法以外的任何地方都無法訪問它。先嚐試在課堂級別聲明它,然後看看會發生什麼。

+0

我已經嘗試在類級別聲明它,但它會引發IOException。所以我試圖把它放在一個「try..throw」中,但它說我必須在一個方法中做到這一點。 – user1546011 2012-07-23 14:12:39

0

我會嘗試在這裏放一些代碼來解釋我的意思。 在類級別聲明變量socket2。

的MulticastClient_v2類應該有類型的公共consturctor:

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

如果端口號不會改變,您可以在硬代碼,但這種方式更靈活。 在run方法中,您現在可以使用初始化的套接字,並且仍然可以從類外部訪問它。只是爲了記錄,儘管我寧願你通過線程上的另一種方法進行訪問,但這可能是另一個線程的討論;)