快速接收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();
}
}
}