接收以固定时钟速率发送的 UDP 数据包流

Receive streaming of UDP packets sent at fixed, clocked rate

我需要以每秒 1000 个数据包的固定速率接收 UDP 数据包流。它们由 28 个字节的有效载荷组成,其中前四个字节 (Uint32) 是数据包序列号。发送方是同一本地网络上的嵌入式设备,地址和端口是相互已知的。我不希望收到 每个 数据包,但主机的设计应使其不会增加固有的 UDP 协议限制。

我以前对 UDP 和套接字的一般经验有限(只是从 android phone 上的传感器应用程序随意流式传输到 PC,用于小型演示项目)。

我不确定快速接收所有数据包的最明智方法是什么。我想象某种循环,或者某种自我重新触发的接收操作。我研究了同步接收和异步接收之间的区别,以及基于任务的异步模式 (TAP),但我还不是很有信心。看起来是个简单的任务,但对我来说理解起来还是很复杂。

所以问题是:

  1. Is UdpClient class suitable to a scenario like this, or am I better off going with the Socket class? (or another one, by the way)

  2. Should I use synchronous or asynchronous receiving? If I use synchronous, I am afraid of losing packets, and if I use asynchronous, how should I clock/throttle the receive operations so that I don't start them at a rate that's too large?

  3. I thought about a tight loop testing for UdpClient.Available() like below. Would it be a good design choice?

while (running)
{
    if (udpSocket.Available() > 0)
    {
        // do something (what?)
    }
}

只需使用 UdpClient.Receive() 以尽可能快的速度(或对您的应用程序方便的速度)从您的 UdpClient 读取。如果没有传入数据包,Receive() 操作将阻塞(等待),因此连续调用 Receive() 三次将始终 return 你三个 UDP 数据包。

一般情况下,在接收UDP数据包时,您不必担心发送速率。只有发件人需要担心发送速率。所以对发送方的相反建议是:不要尽可能快地发送大量 UDP 数据包。

所以我的答案是:

  1. 是的,使用 UdpClient。

  2. 使用同步接收。在接收线程中的循环 运行 中调用 UdpClient.Receive(),或者在程序的主循环中调用 UdpClient.Receive(),随您喜欢。

  3. 您不需要检查可用数据。 UdpClient.Receive() 将阻塞直到有数据可用。

  4. 不要害怕在接收UDP时丢失数据包:你几乎永远不会在接收主机上丢失UDP数据包,因为你在接收时做错了什么。 UDP 数据包大多被网络组件(例如网络路径上某处的路由器)丢弃,它们发送(转发)UDP 数据包的速度不能像接收它们那样快。

一旦数据包到达您的机器,您的 OS 会进行相当数量的缓冲(例如 Linux 上的 128k),因此即使您的应用程序在 1 秒内没有响应,它也会不丢失任何 UDP 数据包。