2014-02-07 188 views
2

我要听的UDP 3个不同的端口,在我的Java项目。我实现我的系统如下:如何在Java中侦听UDP端口?

我有一个UDPMessageListener类实现Runnable。我想创建3个线程作为这个对象运行。

我有一个名为“UDPPacketProcessor”的接口,它有一个onPacketReceived方法。

每UDPMessageListener有UDPPacketProcessor实例,并指示UDP数据包注册为UDPPacketProcessor的对象。

而且我有一个DatabaseProc需要服务于来自3个不同UDP端口的消息的类。 DatabaseProc实现UDPPacketProcessor 将其自身注册到那些3 UDPMessageListener类。

从理论上说,根据我的Java知识,不能有任何的问题,3个运行的线程监听到3个端口,以及接收到的数据包,叫我的主要单身对象的方法的方法。然而,当我运行该程序,只有一个端口被听取。我只能在HBMessageListener工作正常,其他人不回应。当我绕过HBMessageListener(注释掉我运行它的行)时,我现在可以看到只有AlarmMessageListener有效。我错在哪里?

UDPMessageListener.java

public class UDPMessageListener implements Runnable { 

int port; 
byte[] receiveData; 
DatagramSocket udpListeningSocket; 
UDPPacketProcessor processor; 
public UDPMessageListener(UDPPacketProcessor listener,int localPort){ 
    port = localPort; 
    this.processor = listener; 
    receiveData = new byte[SRPDefinitions.BYTE_BUFFER_MAX_LENGTH]; 
    try { 
     udpListeningSocket = new DatagramSocket(port); 
    } catch (SocketException e) { 
     System.out.println("Socket bind error in port: " + port); 
     e.printStackTrace(); 
    } 
} 

@Override 
public void run() { 
    while(true){ 
     DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); 
     try { 
      udpListeningSocket.receive(receivePacket); 
      System.out.println("Received UDP Packet from Port:" + port); 
      processor.onPacketReceived(receivePacket, port); 

     } catch (IOException e) { 
      System.out.println("UDP Listener end up with an exception:"); 
      e.printStackTrace(); 
     } 

    } 
} 
} 

UDPPacketProcessor.java

public interface UDPPacketProcessor { 
public void onPacketReceived(DatagramPacket receivedPacket,int localPort); 
} 

DatabaseProc.java

public class DatabaseProc implements UDPPacketProcessor{ 

private static DatabaseProc instance = null; // for singleton. 

byte[] receiveData; 
byte[] sendData; 
ByteBuffer systemMessageByteBuffer; 

UDPMessageListener HBMessageListener; 
UDPMessageListener AlarmMessageListener; 
UDPMessageListener TrackMessageListener; 

private DatabaseProc(){ 
    receiveData = new byte[SRPDefinitions.BYTE_BUFFER_MAX_LENGTH]; 
    sendData = new byte[SRPDefinitions.BYTE_BUFFER_MAX_LENGTH]; 
    HBMessageListener = new UDPMessageListener(this,SRPDefinitions.HB_PORT); 
    AlarmMessageListener = new UDPMessageListener(this,SRPDefinitions.ALARM_PORT); 
    TrackMessageListener = new UDPMessageListener(this,SRPDefinitions.TRACK_PORT); 
} 

public void run(){ 
    runListeners(); 
} 

private void runListeners(){ 
    HBMessageListener.run(); 
    AlarmMessageListener.run(); 
    TrackMessageListener.run(); 
} 

public static DatabaseProc getInstance(){ 
    if(instance == null){ 
     instance = new DatabaseProc(); 
    } 
    return instance; 
} 

@Override 
public void onPacketReceived(DatagramPacket receivedPacket, int localPort) { 
    String strIPAddress =receivedPacket.getAddress().toString(); 

    ByteBuffer buffer = ByteBuffer.allocate(receivedPacket.getLength()); 
    System.out.println("Received Packet Length: " + receivedPacket.getLength() + "/" + receivedPacket.getData().length); 
    buffer.order(ByteOrder.LITTLE_ENDIAN); 

    buffer.put(receivedPacket.getData(),0,receivedPacket.getLength()); 
    buffer.position(0); 

    if(localPort == SRPDefinitions.HB_PORT){ 
     System.out.println("HB Message Received from " + strIPAddress + "!"); 
     SRPHeartBeatMessage message = new SRPHeartBeatMessage(buffer); 
     //message.print(); 
    } 
    if(localPort == SRPDefinitions.ALARM_PORT){ 
     System.out.println("ALARM Message Received from " + strIPAddress + "!"); 
     SRPAlarmMessage message = new SRPAlarmMessage(buffer); 
     message.print(); 
    } 
    if(localPort == SRPDefinitions.TRACK_PORT){ 
     System.out.println("TRACK Message Received from " + strIPAddress + "!"); 
    } 
} 
+0

你是如何确保只有一个端口是开放的?请发布'netstat'的输出(正确选项列出侦听UDP套接字取决于您的操作系统)。 – chrylis

+0

感谢您的即时回复。我的3个端口是42010,42020和42030.HB端口是42030(我只能得到响应的端口,是第一个运行的端口)。我从终端查询每个3端口的netstat输出,并且所有进程ID都是一样的: – fercis

+0

'fercis @ fercis2014:〜$ sudo netstat -lpn | grep:42030 udp6 0 0 ::: 42030 ::: * 3458/JAVA fercis @ fercis2014:〜$ sudo的netstat的-lpn | grep的:42010 UDP6 4224 0 ::: 42010 ::: * 3458/JAVA fercis @ fercis2014:〜$ sudo的netstat的-lpn | grep:42020 udp6 0 0 ::: 42020 ::: * 3458/java' – fercis

回答

2

该问题出现在DatabaseProc类中。将runListeners更改为以下。

private void runListeners(){ 
    new Thread(HBMessageListener).start(); 
    new Thread(AlarmMessageListener).start(); 
    new Thread(TrackMessageListener).start(); 
} 

编辑

的解释是:UDPMessageListener.run()被直接调用,它不创建一个新的线程异步执行。使用您的代码时,执行将永远不会出现在HBMessageListener.run()方法中,因为它处于无限循环中。您需要并行化听众,以便所有人都可以收听。

+0

太棒了!谢谢 :) – fercis