加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – android UDP不可靠

发布时间:2020-12-15 02:17:50 所属栏目:Java 来源:网络整理
导读:我使用 Android有极端的UDP数据包丢失,这没有任何意义.情况如下: PC running java client connected to home network Phone running java server (android) connected to home network Home router is a brand new WRT1900ac. Network has internet connect
我使用 Android有极端的UDP数据包丢失,这没有任何意义.情况如下:

  1. PC running java client connected to home network
  2. Phone running java server (android) connected to home network
  3. Home router is a brand new WRT1900ac. Network has internet connectivity.
  4. UDP packets are small (< 15 bytes)

症状:

  1. If PC sends UDP packet to another PC (both on same network) it works very well (almost no packets lost).

  2. If Android sends UDP packet to PC on the same network it also works very well (almost no packets lost).

  3. If PC sends UDP to Android on the same network I get extreme packet losses (50% of the time or more – but it varies).

大多数情况下,我被迫发送数据包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,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();
    }

解决方法

我有一些灾难性的结果,一些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();

希望这可以帮助.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读