4

我在使用 Android 时遇到了极端的UDP 数据包丢失,这没有任何意义。情况如下:

  1. 运行连接到家庭网络的 java 客户端的 PC
  2. 运行连接到家庭网络的 java 服务器 (android) 的手机
  3. 家用路由器是全新的WRT1900ac。网络具有互联网连接。
  4. UDP 数据包很小(< 15 字节)

症状

  1. 如果 PC 将 UDP 数据包发送到另一台 PC(都在同一网络上),它工作得很好(几乎没有数据包丢失)。

  2. 如果 Android 将 UDP 数据包发送到同一网络上的 PC,它也可以很好地工作(几乎没有数据包丢失)。

  3. 如果 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();
    }
4

1 回答 1

0

一些 Android 设备通过 WiFi 向 TFTP(基于 UDP)服务器发送文件时,我遇到了灾难性的结果,但它似乎与其他 Android 设备配合得很好。

数据块(从设备到服务器)被正确发送,但确认块(从服务器到设备)似乎丢失了。

原来我必须获得一个多播锁才能让那些有故障的设备正常工作(归功于https://www.b4x.com/android/forum/threads/enable-multicast.43321/#post-263242

WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock multicastLock = wifi.createMulticastLock("multicastLock");
multicastLock.setReferenceCounted(true);
multicastLock.acquire();

...

multicastLock.release();

希望这可以帮助。

于 2017-07-04T16:08:31.137 回答