Android UDP间歇性地接收丢包

时间:2017-01-05 17:32:38

标签: android sockets networking udp video-streaming

我有一个Nexus 5X,它有间歇性的接收问题。我已经能够在华硕平板电脑,两个三星平板电脑和Kindle Fire上运行代码,没有任何问题。代码基于此存储库: https://github.com/moonlight-stream/moonlight-common/blob/master/src/com/limelight/nvstream/av/video/VideoStream.java

以下是相关代码:

WifiManager wifiMgr = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "Player");
wifiLock.setReferenceCounted(false);
wifiLock.acquire();

rtp = new DatagramSocket(RTP_PORT);
rtp.setReceiveBufferSize(256*1024);

// Receive thread
Thread t = new Thread() {
@Override
public void run() {
    while (!isInterrupted())
    {
        try {
            // Pull the next buffer in the ring and reset it
            buffer = ring[ringIndex].getBuffer();

            // Read the video data off the network
            packet.setData(buffer, 0, buffer.length);
            rtp.receive(packet);

            // Do processing here
        } catch (IOException e) {
            return;
        }
    }
}
};
threads.add(t);
t.setName("Video - Receive");
t.setPriority(Thread.MAX_PRIORITY - 1);
t.start();

我确信我可以正确地将UDP流发送到设备。大多数数据包都是正确接收的。但是,我在方法跟踪中注意到了

rtp.receive(packet);

可以阻止100s-1000s毫秒。当在完全相同的架构中的不同设备上运行时,我看到基本上100%的数据包成功,最大块可能是60ms。

我在2.4G和5G上尝试过多个路由器。问题出在设备上。

正在发送的数据包是UDP直接到设备。网络上没有IP冲突。

对可能出现的问题有任何疑问?非常感谢你!

编辑:我应该注意CPU使用率约为2%,内存使用量约为10MB

编辑2:我创建了一个简单的应用程序来简单地调查此问题。我看到了同样的结果。我会在几台设备上看到30,000多个连续数据包而没有一个丢包。我会在Nexus 5X上每隔几秒丢弃一系列数据包。我有人在他们的Nexus 5X上远程运行这个测试应用程序,并且他们报告没有丢弃数据包。据我所知,所有迹象都指向司机/无线电问题......

package com.udp_receiver_test;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.ByteBuffer;

public class MainActivity extends AppCompatActivity {

    private WifiManager.WifiLock wifiLock;
    Thread t;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "Player");
        wifiLock.setReferenceCounted(false);
        wifiLock.acquire();

        // Use sustained performance mode on N+ to ensure consistent
        // CPU availability
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            getWindow().setSustainedPerformanceMode(true);
        }


        startListenThread();
    }

    private void startListenThread()
    {
        t = new Thread() {
            @Override
            public void run()
            {
                DatagramSocket socket;

                int nextSequenceNumber = 0;

                ByteBuffer byteBuffer;

                int BufferSize = 1292;
                int NumRingElements = 784;
                long correctPacketCounter = 0;

                byte ring[][] = new byte[NumRingElements][1292];

                try {
                    socket = new DatagramSocket(12345);
                    socket.setReceiveBufferSize(256 * 1024);
                } catch (Exception e) {
                    e.printStackTrace();
                    return;
                }

                byte[] buffer;
                int ringCounter = 0;
                DatagramPacket packet = new DatagramPacket(new byte[1], 1);
                //short rtpSequenceNumber;
                int sequenceNumber;

                while (!isInterrupted()) {
                    try {
                        buffer = ring[ringCounter];

                        packet.setData(buffer, 0, buffer.length);
                        socket.receive(packet);

                        if (packet.getLength() > 20) {

                            // Read the RTP sequence number field (big endian)
                            byteBuffer = ByteBuffer.wrap(buffer);
                            byteBuffer.position(16);
                            sequenceNumber = (byteBuffer.getInt() >> 8) & 0xFFFFFF;

                            if (sequenceNumber != nextSequenceNumber) {
                                Log.d("TAG", "Not next sequence number - Got:" + sequenceNumber + " Expected:" + nextSequenceNumber);
                            } else {

                                if (((++correctPacketCounter) % 100) == 0)
                                {
                                    Log.d("TAG", "Correct packets = " + correctPacketCounter);
                                }

                            }

                            nextSequenceNumber = (sequenceNumber + 256) % 65535;
                        } else {
                            Log.d("TAG", "Message too short");
                        }

                        ringCounter = (ringCounter + 1) % NumRingElements;
                    } catch (Exception e) {
                        e.printStackTrace();
                        return;
                    }
                }
            }
        };
        t.setName("Receiver");
        t.setPriority(Thread.MAX_PRIORITY - 1);
        t.start();
    }

    @Override
    public void onStop()
    {
        super.onStop();
        wifiLock.release();
        if (t.isAlive()) {
            t.interrupt();
        }
    }
}

0 个答案:

没有答案