首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在一些Android设备上严重丢失UDP数据包

在一些Android设备上严重丢失UDP数据包
EN

Stack Overflow用户
提问于 2015-05-25 07:11:26
回答 4查看 4.3K关注 0票数 9

我搜索了interwebz,但没有结果。我们面临的问题是,一些Android设备出现了严重的数据包丢失。为了给出一些背景信息,应用程序连接到特定的Wifi并查找端口17216上广播的UDP数据包。这些数据包的大小为832字节(不包括包装的头),并且以每秒4次的正常速率发送。

我们只在两个设备上遇到了这个问题,一个是低端Turbox Rubik II平板电脑,另一个是ASUS备忘录Pad Pad 7。我们测试过的其他设备(手机和平板电脑)都在规定的定期间隔内收集数据包。

接收数据包的功能如下:

代码语言:javascript
运行
复制
public void run()
{
    while (isUDPServerRunning)
    {
        try
        {
            socket.receive(packet);

            ProcessRawPacketData();

            DisplayLoggingInfo();

        }
        catch (IOException e)
        {
            Log.e("receive", e.getMessage());
            e.printStackTrace();
        }
    }
}

这是Runnable的一部分。因此,创建了套接字:

代码语言:javascript
运行
复制
byte[] buffer = new byte[1024];

DatagramSocket socket;
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

onCreate()扩展的Service方法中初始化套接字:

代码语言:javascript
运行
复制
socket = new DatagramSocket(SERVERPORT);

这些数据包正在被Wifi模块接收。我们已经确认,通过查找其中一个设备并安装一个数据包嗅探器,这个问题一定是与代码相关的。

在受影响的设备上,数据包被正确地接收了几秒钟,然后有一个完整的丢失,持续了几秒钟,所以我估计损失超过50%。

任何帮助都将不胜感激。我们正在拔头发。

Update I错误地使用了数据包嗅探器。包嗅探器似乎也丢失了根设备上的几个相关数据包。不过,有时候,只需启动数据包嗅探器就可以解决这个问题!像下面建议的那样,打开/关闭蓝牙似乎没有什么区别。这会是另一个硬件问题吗?

更新2是我在socket.receive()行之后立即打印的日志的一个例子。注意它是如何跳过半分钟的数据包,然后工作几秒钟。

代码语言:javascript
运行
复制
05-25 15:44:38.670: D/LOG(4393): Packet Received
05-25 15:44:38.941: D/LOG(4393): Packet Received
05-25 15:45:09.482: D/LOG(4393): Packet Received
05-25 15:45:09.716: D/LOG(4393): Packet Received
05-25 15:45:09.928: D/LOG(4393): Packet Received
05-25 15:45:10.184: D/LOG(4393): Packet Received
05-25 15:45:10.451: D/LOG(4393): Packet Received
05-25 15:45:10.661: D/LOG(4393): Packet Received
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-06-02 22:02:20

数据包丢失(当然,如您所知)可以在传输的多个阶段发生:

  1. 从服务器发送
  2. 通过网络传输
  3. 客户端的物理接收和硬件处理
  4. 内核/OS中数据包的处理/缓冲
  5. 处理/缓冲应用程序中的数据包。

您可以通过让其他设备在连接到同一个Wifi路由器时监听相同的广播,快速检查第1点还是第2点是否是问题。听起来你已经这么做了,这是没有问题的。(请注意,如果在服务器上运行WireShark转储,步骤2(有时甚至1)中丢弃的数据包可能不会丢失。)

因此,从第3点到第5点很可能是问题所在,它们可能更难分开。

以下是几件可能有帮助的事情:

  • 就像@Mick建议的那样,不要只在收到数据包时打印出来,而是为每个数据包提供一个增加的ID号,以确定您是否确实丢失了一个数据包,还是它只是被延迟了。
  • 将您的数据包接收代码移动到它自己的线程中(如果还没有),并将该线程的设置优先级移动到优先级,以尽量减少代码阻塞午餐线的可能性。考虑到备忘录Pad是一台四核1.2GHz机器,MAX_PRIORITY甚至不应该是必要的,但是如果您目前没有在自己的专用线程中运行接收循环,您可能会看到hick-up。如果这解决了一些问题,只需有一个最小的接收循环,将数据包插入到您自己的缓冲区队列中,并有一个独立的线程处理它们。
  • 检查/增加数据包缓冲区的大小,以便通过setReceiveBufferSize(.) (这里有更详细的Java参考 )接收数据包。请确保指定可容纳多个数据包的大小。考虑到运行数据包嗅探器有时似乎会有所帮助,听起来确实可能有一些套接字设置可以改善事物,而嗅探器恰好设置了这些设置。
  • 在服务器上,您还可以在数据包中添加一个标签,告诉所有涉及的设备如何对待该数据包。如果您调用可靠性),您是在要求每个参与其中的人优化他们的数据包处理以获得最大的可靠性。并不是所有的设备都会在意,但这可能会产生不同的效果。
  • 您可以尝试使用DatagramChannels而不是DatagramSockets,然后使用选择()等待下一个数据包的读取。虽然这在技术上没有什么不同,但有时使用不同的API调用可以解决问题。
  • 不幸的是,Android是一个非常异构的环境,许多制造商将提供他们自己的内核模块等。这也带来了各种不兼容或非标准行为无处不在。你可能会找到一个定制的ROM (氰基,等等?)你的一个或两个问题设备。如果安装它而不是工厂ROM修复了您的问题,那么它是制造商提供的(内核)网络驱动程序中的一个bug,在这种情况下,您可能会幸运地找到一个解决方案,或者您可以向它们提交错误报告,但通常,您可能只需选择这些设备作为不支持的在Play Store中,以避免坏的评论.

最后,这里有一个解决方案,可以肯定地解决这个问题:

向客户端添加一些检测丢弃数据包的代码,如果掉包率太高,则打开到服务器的TCP连接,这将保证数据包的传递。考虑到您的数据包很小且不频繁,而且只有少数设备需要使用此机制,我认为这不会对您的服务器负载造成问题。如果您没有办法更改服务器代码以提供TCP流,则可以编写一个独立的代理服务器来收集UDP数据包并通过TCP提供这些数据包。如果您可以在与原始服务器相同的机器上运行它,您甚至知道它位于哪个IP地址(与到达的UDP数据包的源地址相同)。

票数 5
EN

Stack Overflow用户

发布于 2015-06-02 13:48:24

只是猜测一下,但是你在数据包上的计算需要多长时间?是否有可能套接字分配的缓冲区填满并开始删除包?

我知道,这听起来不太可能以4KB/s的速度.但是,如果你的计算时间超过250毫秒,这迟早会发生。这也解释了为什么有些设备工作起来像一种魅力,而另一些则不然。

您是否尝试删除计算,只打印“已接收的包”消息以进行调试?

票数 1
EN

Stack Overflow用户

发布于 2015-06-02 22:00:07

有趣的是,这两个正在经历UDP数据包丢失的设备都有Mediatek SoC。您的其他测试设备有相同的芯片组吗?

这可能是那些SoC的Wi驱动程序中的一个漏洞。由于它只出现在UDP中,而且并不总是100%,到目前为止,它可能还没有被所有人注意到。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30432974

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档