java - android UDP unreliability

时间:2016-12-19 14:21:26

标签: java android udp packet loss

Android使用极端 UDP数据包丢失并且没有意义。情况如下:

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

症状

  
      
  1. 如果PC将UDP数据包发送到另一台PC(同一网络),则效果非常好(几乎没有数据包丢失)。

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

  4.   
  5. 如果PC在同一网络上向Android发送UDP,我会收到极端的数据包丢失(50%的时间或更多 - 但会有所不同)。

  6.   

大多数时候,我被迫发送数据包10次才能通过。其他时候都会有一些延迟。非常奇怪的行为,只发生在android的接收端。如果我用在pc上运行相同代码的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();
    }

1 个答案:

答案 0 :(得分:0)

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

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

原来我必须获取多播锁才能让这些有故障的设备正常工作(信用到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();

希望这有帮助。