2015-12-02 24 views
0

我有一個設備使用UDP數據報來回覆命令。我試圖想出一種方法來保證響應來自特定請求。當我運行下面的代碼時,我得到了前兩個,有時是第三個請求,然後它掛起並超時接收。我已經嘗試了幾種不同的方法來解決它(因此,同步和iQueuePointer接收超時)。這裏是一個運行的例子:Java Datagram發送和接收不保持同步

Listening for X-Air responses 
Sending X-Air requests 
Servicing request 6 
Send loop - bWait=true request.size=6 iQueuePointer=6 
/info,ssssV0.04XR12-24-00-6EXR121.10 from 6 
Removed 6 
Servicing request 5 
Send loop - bWait=true request.size=5 iQueuePointer=5 
/ch/01/config/name,sPreach Mic from 5 
Removed 5 

下面的代碼:

public static final Object socketLock = new Object(); 
public static DatagramSocket socket; 
public static ArrayList<String> request = new ArrayList<>(); 
public static int iQueuePointer; 
public static boolean bWait; 

public static void main(String[] args) { 
    new Main(); 
} 

private Main() { 

    try { 
     socket = new DatagramSocket(); 
    } catch (SocketException e) { 
     e.printStackTrace(); 
    } 
    new Thread(receiveRunnable).start(); 
    new Thread(sendRunnable).start(); 
    iQueuePointer++; 
    request.add("/info"); 
    iQueuePointer++; 
    request.add("/ch/01/config/name"); 
    iQueuePointer++; 
    request.add("/ch/02/config/name"); 
    iQueuePointer++; 
    request.add("/ch/03/config/name"); 
    iQueuePointer++; 
    request.add("/ch/04/config/name"); 
    iQueuePointer++; 
    request.add("/ch/05/config/name"); 
    iQueuePointer++; 
} 

private Runnable sendRunnable = new Runnable() { 
    @Override 
    public void run() { 
     System.out.println("Sending requests"); 
     while(socket != null) { 
      if(!bWait && request.size() > 0 && request.size() < iQueuePointer) { 
       iQueuePointer--; 
       bWait = true; 
       System.out.println("Servicing request " + iQueuePointer); 
       //synchronized (socketLock) { 
        try { 
         socket.send(new DatagramPacket(request.get(0).getBytes(), 
           request.get(0).getBytes().length, 
           InetAddress.getByName("192.168.0.180"), 10024)); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
       //} 
      } 
     } 
     System.out.println("sendRunnable ended"); 
    } 
}; 

private Runnable receiveRunnable = new Runnable() { 

    @Override 
    public void run() { 
     System.out.println("Listening for responses"); 
     byte[] data = new byte[1024]; 
     DatagramPacket packet = new DatagramPacket(data, data.length); 
     while(socket != null) { 
      //synchronized (socketLock) { 
       try { 
        //socket.setSoTimeout(5000); 
        socket.receive(packet); 
        if (packet.getLength() > 0 && socket != null) { 
         System.out.println(new String(Arrays.copyOf(packet.getData(), packet.getLength())) 
           + " from " + iQueuePointer); 
         request.remove(0); 
         System.out.println("Removed " + iQueuePointer); 
         bWait = false; 
        } 
       } catch (Exception e) { 
        if (!e.toString().contains("Receive timed out")) { 
         e.printStackTrace(); 
        } else { 
         System.out.println("Receive loop - bWait=" + bWait + " request.size=" + request.size() 
           + " iQueuePointer=" + iQueuePointer); 
        } 
       } 
      //} 
     } 
     System.out.println("receiveRunnable ended"); 
    } 
}; 

回答

0

在UDP,你不能假設的迴應以相同的順序到達的請求被髮送,或者甚至在所有的,你也不能假設他們只到達一次。

您必須在兩者中使用序列號來匹配它們,否則不會有任何掛起的請求,並在發出請求之前不斷髮出請求,然後您仍然需要以某種方式處理重複項。

注意:您需要重新創建DatagramPacket或至少每次在讀取循環周圍重新設置其長度,否則它可以保持縮小到目前爲止收到的最小數據報的大小。