2014-02-07 248 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