我在使用 Android 时遇到了极端的UDP 数据包丢失,这没有任何意义。情况如下:
- 运行连接到家庭网络的 java 客户端的 PC
- 运行连接到家庭网络的 java 服务器 (android) 的手机
- 家用路由器是全新的WRT1900ac。网络具有互联网连接。
- UDP 数据包很小(< 15 字节)
症状:
如果 PC 将 UDP 数据包发送到另一台 PC(都在同一网络上),它工作得很好(几乎没有数据包丢失)。
如果 Android 将 UDP 数据包发送到同一网络上的 PC,它也可以很好地工作(几乎没有数据包丢失)。
如果 PC 在同一网络上将 UDP 发送到 Android,我会出现极端的数据包丢失(50% 或更多的时间 - 但它会有所不同)。
大多数时候,我被迫发送数据包 10 次才能通过。其他时间都经过了相当长的延迟。非常奇怪的行为,只发生在 android 的接收端。如果我用在 java 上运行相同代码的 pc替换android 或者只是通过 Packet Sender 的 UDP 服务器接收数据包,我没有丢失问题。我注意到的另一件事是,如果不是通过路由器,而是通过另一个没有互联网连接或没有其他客户端的接入点,性能似乎会显着提高。这是意料之中的,但我的问题是为什么 Android 的接收端表现如此糟糕并丢失了这么多数据包。当 Android 被另一台运行相同代码并在同一网络上的 PC 替换时,没有问题。发送Android
数据包也没有问题(没有数据包丢失)。因此,在接收端它必须是其他与 android 相关的东西......
我也尝试用 Packet Sender 替换 PC 代码,我得到了相同的结果。问题似乎是Android的接收端。我在 PC 端和 android 上运行相同的 UDP 代码。
UDP发送代码很简单:
public void sendMessage(String message)
{
try {
DatagramSocket ds = new DatagramSocket();
DatagramPacket dp;
InetAddress local = InetAddress.getByName(ipPool);
dp = new DatagramPacket(message.getBytes(), message.length(), local, port);
ds.setBroadcast(true);
ds.send(dp);
ds.close();
} catch (Exception e) {
e.printStackTrace();
}
}
android 上的 UDP 接收代码位于 UDP 服务器类中:
public class UDP_Server
{
CommandParser commandParser;
public UDP_Server(MainActivity mainActivity)
{
Log.i("Udp tutorial", "---------------------------Starting UDP SERVER");
commandParser = new CommandParser(mainActivity);
String text;
int server_port = 9876;
try
{
DatagramSocket s = new DatagramSocket(server_port);
s.setBroadcast(true);
//s.setReceiveBufferSize(163840);
while (true)
{
byte[] message = new byte[1024];
DatagramPacket p = new DatagramPacket(message, message.length);
s.receive(p);
text = new String(message, 0, p.getLength());
Log.d("Udp tutorial","message:" + text);
//commandParser.parseCommand(text);
//s.close();
}
} catch (SocketException e)
{
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDPServer.java 类通过主活动“onCreate()”方法实例化:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
wm = (WifiManager) getSystemService(WIFI_SERVICE);
Log.i("Udp tutorial", "---------------------------HERE 1");
Thread thread = new Thread(new Runnable()
{
public void run()
{
UDP_Server svr = new UDP_Server(MainActivity.this);
}
});
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
// TCPServer server = new TCPServer();
}