快速接收UDP数据包

问题描述:

我有一个UDP侦听器线程,它是循环的,并在收到数据包后调用方法。它工作得很好,只是当第一个包之后有多个包快速到达时,该方法没有被调用。快速接收UDP数据包

两个数据包一次又一次地发送,第一个是2个字节长,第二个是3个字节长。 receive()方法往往会在第二个数据包到达时被触发。

这里是UDP监听器类:

public class UDPListener extends Thread{ 
    private boolean running = true; 
    byte[] data = new byte[1500]; 
    DatagramPacket packet = new DatagramPacket(data, data.length); 

    public void run() { 
     Log.v("MR", "Runs"); 
     try { 
      while(running) { 
       Log.v("MR", "Listening... "); 

       socket.receive(packet); 
       Log.v("MR", "Received Data: " + packet.getData()[0] + "; Length: " + packet.getLength()); 

       device.post(new Runnable() { 
        public void run() { 
         device.receive(packet.getData(), packet.getData().length);       
        } 
       }); 

      } 
     } catch (Throwable e) { 
      e.printStackTrace(); 
      Log.v("MR", "Failed receiving"); 
     } 

    } 
} 

这里是device.receive()方法:

public final void receive(byte[] inData, int length) { 
    data = inData; 
    dataLength = length; 
    Log.v("MR", "Receive(): Data: +" + data[0] + "; Length: " + String.valueOf(data.length)); 
} 

这里是Log结果的一部分:

10-18 17:24:34.393 Received Data: 79; Length: 3 
10-18 17:24:34.393 Listening... 
10-18 17:24:34.393 Receive(): Data: +79; Length: 1500 
10-18 17:24:34.393 Receive(): Data: +79; Length: 1500 
10-18 17:24:34.413 Received Data: 6; Length: 2 
10-18 17:24:34.413 Listening... 
10-18 17:24:34.413 Received Data: 79; Length: 3 
10-18 17:24:34.413 Listening... 
10-18 17:24:34.413 Receive(): Data: +79; Length: 1500 
10-18 17:24:34.413 Receive(): Data: +79; Length: 1500 
10-18 17:24:34.423 Received Data: 6; Length: 2 
10-18 17:24:34.423 Listening... 

由于可以看到数据包实际上正在进入,所以第二个(长度:3)数据包仅更频繁地调用receive()。

'device'是一个自定义视图,带有receive()方法。 我也试着用Runnable处理程序和runOnUiThread(),但结果相同。 我假设UI线程不能更新得太快或类似。

此外,为什么线程日志中的实际长度和resume()日志中的字节数为1500个?它应该是通过相同的数据包。

我看到有80多个这个问题的意见。解决方案是使用处理程序向UI发送消息,并在新数据包到来之前重新初始化data []数组和DatagramPacket。

工作代码为:

public static class UDPListener extends Thread{ 
     private boolean running = true; 
     Message msg; 
     byte[] data; 
     DatagramPacket packet; 

     public void run() { 
      try { 
       while(running) { 
        data = new byte[1500]; 
        packet = new DatagramPacket(data, data.length); 

        //Blocks and waits for a packet 
        socket.receive(packet); 

        //Send packet message to UI 
        msg = UDPReceiveHandler.obtainMessage(); 
        msg.obj = packet; 
        UDPReceiveHandler.sendMessage(msg); 

       } 
      } catch (Throwable e) { 
       e.printStackTrace(); 
      } 
     } 
    }