2012-07-23 45 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方法中,您现在可以使用初始化的套接字,并且仍然可以从类外部访问它。只是为了记录,尽管我宁愿你通过线程上的另一种方法进行访问,但这可能是另一个线程的讨论;)