C:Linux套接字:Recvfrom()获取UDP数据包的速度太慢

时间:2016-03-02 13:00:39

标签: c sockets udp recvfrom

我正在以 10Mbps 的速率接收UDP数据包。每个数据包由 1109字节左右构成。 因此,我在 eth0 上收到的信息超过 1pkt / ms 。 C中的recvfrom()接收数据包并将数据包传递给Java。 Java会对数据包进行过滤并进行必要的处理。

瓶颈是:

  1. recvfrom()太慢:提取时间超过10毫秒可能因为它没有获得CPU。

  2. 通过接口(JNI)将数据包从C传递到Java需要1-2毫秒。

  3. Java本身的数据包处理需要0.5到1秒,具体取决于是否需要进行数据库插入或图像处理。

  4. 因此,问题是许多延迟加起来并且超过一半的数据包丢失。

    可能的解决方案可能是:

    1. 完全排除对C recvfrom()的需求并直接在Java中实现UDP提取(注意:首先,C的recvfrom()实现为接收原始数据包而不是UDP)。此解决方案可能会减少JNI传输延迟。

    2. 在Java中的UDP接收函数上实现多线程。但是在序列的UDP数据包中需要ID,因为在多线程中不能保证传入数据包的顺序。 (但是,在该特定程序中,需要订购数据包)。此解决方案可能有助于接收所有数据包,但需要修改发送数据的协议以添加序列标识符。由于多线程,接收器可能有更高的机会获得CPU,并且可以快速获取数据包。

    3. 在Java中,阻塞队列可以实现为存储传入数据包的巨大缓冲区。然后,Java解析器可以使用来自此队列的数据包来处理它。但是,它不确定接收器功能是否足够快并将所有接收的数据包放入队列而不丢弃任何数据包。

    4. 我想知道哪些解决方案可能是最佳的,或者上述解决方案的组合可行。任何帮助或建议将不胜感激。

2 个答案:

答案 0 :(得分:2)

这次爆发有多长?它是连续的还会永远持续下去?那么你需要更强大的硬件来处理负载。可能是一些负载平衡,其中多个服务器处理传入的数据。

爆发只会持续短暂的诡计,比如最多一秒或两秒?然后让较低级别尽可能快地读取所有数据包,并放入队列,让上层在其自己的时间内从队列中获取消息。

答案 1 :(得分:0)

听起来你可能在阻塞模式下使用套接字调用recvfrom(),在这种情况下,在下一个数据包到达之前它不会返回。如果数据包以10ms的间隔发送,可能是由于发送端有一些延迟,那么阻塞recvfrom()呼叫的循环似乎每个需要10ms。将套接字设置为非阻塞,并使用select()之类的内容来决定何时调用它。然后分析一切,看看真正的瓶颈在哪里。我的赌注是一个或多个JNI直通。

请注意,recvfrom()不是" C"功能,它是一个系统调用。 Java的功能只是在它上面添加图层。