如何通过 UDP 发送实时数据?

Posted

技术标签:

【中文标题】如何通过 UDP 发送实时数据?【英文标题】:How do I send real-time data over UDP? 【发布时间】:2011-04-14 09:36:01 【问题描述】:

我必须尽可能快和实时地通过 UDP 发送一系列视频帧,虽然我已经掌握了基础知识,但我遇到了各种各样的困难。我的一些目标:

    数据通常会通过拨号发送(因此是 UDP 而不是 TCP),但还需要支持快速以太网。

    偶尔丢帧是可以的(因此使用 UDP 而不是 TCP)。

    需要低延迟。远程接收的帧应该是最近发送的帧(在缓冲区中等待的帧不超过几帧)。

    我需要能够检测有效带宽,以便我可以或多或少地压缩帧以保持帧速率。

我已经设法实现了大部分部分:

    我将帧数据分解为一个或多个大约 500 字节的数据报,每个数据报都有一个序列号和其他信息。接收器重新组合整个帧并检测是否有任何数据报丢失。

    如果接收方检测到超过一定百分比的丢帧(例如,过去 10 帧中的 50%),我会向发送方发送一条 TCP 消息以减慢 50%。发送者在随后的每一帧中缓慢地将速度提高 5%。

    使用 System.Net.Sockets.UdpClient 发送和接收数据。

    我有一个单独的 TCP 通道,用于将控制消息返回给发送者。

我现在的主要困难是检测有效带宽和处理延迟,尤其是在拨号时(最大 ~4,000 字节/秒)。例如,如果我尝试使用 TcpClient.Send() 发送 100,000 字节/秒,它们似乎都到达(没有丢弃的数据报),但在最后一个数据报到达时延迟很大。我认为 TcpClient.Send() 函数会阻塞,直到缓冲区能够发送,这会扰乱我当前的算法。

任何人都可以向我指出任何信息来源,以了解如何:

    检测 UDP 上的实际带宽。

    动态调整带宽以适应可用管道的更好算法。

    以所需带宽平稳发送数据。

    一种检测延迟并将延迟降至最低的方法。

上周我一直在旋转我的车轮,每次我解决一个问题时,似乎另一个问题就会抬头。

【问题讨论】:

【参考方案1】:

您还可以为每个数据包添加时间戳。然后您可以检测延迟是否增加。在这种情况下,您发送回一条消息以减少带宽。

在创建连接时,您可以通过很少的数据包检测到延迟。此值在运行时不应更改。

【讨论】:

我确信检测延迟将需要某种数据报计时。例如,我可能需要附加一个时间戳,发送给接收者,然后接收者将其发回(可能使用 TCP 控制通道)。在某种历史队列中找到原始发送时间,差/2 是 aprox。潜伏。我找不到已发布的算法来执行此操作,因此我可以有效地实施。 您甚至不需要知道绝对延迟。由于您要解决的是带宽问题,因此您只需查看帧间时间 - 如果帧以 40 毫秒的间隔发送,但您看到它们以 90 毫秒的间隔发送,那么发送方需要放慢速度。 这样的问题是,随着时间的推移,小的延迟可能会在发送帧之间增加很大的延迟。我最终为收到的每个完整帧发送了一个 ACK​​。在发送方,我会跟踪发送的最后 10 帧、发送时间以及确认时间。如果平均时间太长,我知道要放慢速度。

以上是关于如何通过 UDP 发送实时数据?的主要内容,如果未能解决你的问题,请参考以下文章

用于实时多人游戏的 Node.js UDP

实时数据流到多个客户端

来自机器人通过 UDP 发送的图像在服务器 (PC) 上的实时视频流

如何在 Python 中通过 HTTP 提供来自 UDP 流的数据?

使用 Firebase 函数将实时数据库中的数据发送到电子邮件

有没有办法实时从UDP数据包中提取有效负载并将该有效负载用于其他应用程序?