1

我有一个非常高速率的 UDP 应用程序,我对这里的具体基础有点好奇。我正在使用 c# 异步方法,在 EndReceive 上,我将工作放在一个新线程上,然后调用 BeginReceive。

据我了解,即使我目前处于 EndReceive 和 BeginReceive 之间的代码中,Windows 仍然在此端口上接受 UDP 数据包 - 每当我再次调用 BeginReceive 时,下一个将从堆栈中取出。

假设这一切都是真的(如果不是,请直截了当) - 我可以在这些数据包上指定一个 TTL 吗?我需要向发件人发送响应,并且发件人被配置为在几秒钟后忽略响应。

谢谢

4

3 回答 3

4

当网络接口卡从线路传送数据报时,操作系统将其放入套接字的接收队列中。它在那里等待,直到您使用recvfrom()系统调用或您选择的高级包装器读取它。

getsockopt()您可以通过调用来确定此缓冲区的大小SO_RCVBUF。默认大小和最大大小因操作系统和版本而异。

网络数据报不携带任何时间信息,因此没有内在的方法可以根据时间使它们过期。您选择如何进行实际上取决于您期望延迟的确切来源。

  • 如果您关心从发送到处理的时间,那么您必须协调发送方和接收方之间的时钟,然后让发送方在每个数据报发送之前在每个数据报中放置一个时间戳。这是您可以知道事件之间的实际时间的唯一方法。但请记住,网络延迟可能会有很大差异,因此简单地丢弃所有早于某个数量的数据包可能会导致您丢弃所有数据包。

  • 如果您只关心接收数据包和处理数据包之间的时间(忽略网络延迟),那么您将需要有一个单独的线程在数据报到达时尽快读取它们,记下它们的时间并存储它们在一个内部的、线程安全的队列中。这是很多工作,并且会引入大量开销,因此您可能首先要检查处理延迟的原因。

  • 如果数据包以相当固定的速率发送和/或您关心的不是时间问题,而是未处理数据包的积压问题,那么您可能只想减小接收队列的大小(setsockopt()with SO_RCVBUF)。当接收队列已满时,任何到达的数据报都将被静默丢弃。

于 2012-04-04T01:38:58.403 回答
1

您在数据包太旧时丢弃数据包的要求是特定于应用程序的,并且(AFAIK)不是 UDP 可以为您提供的。Windows 可能会“自动”为您接收和缓冲数据报,但它如何做到这一点是网络堆栈的实现细节。

我将其分为两部分:

  1. 尽快接收和排队消息。
    • 如果您想限制接收队列的大小,即使在这个阶段也可能开始丢弃最旧的消息。
  2. 出队消息:
    • 如果它们太旧,请将它们扔在地板上。
    • 以其他方式处理和确认它们。

第 2 步可能会并行化,以尝试确保您的消费者跟上。

于 2012-04-02T16:04:48.270 回答
1

您可以在发送时指定 TTL,但 TTL 在每个路由器通过时会递减,并且不是基于时间的。这不是您要寻找的领域。

因此,如果一个数据包的 TTL 为 3,则它在第一个路由器之后变为 2,在第二个路由器之后变为 1,在第三个路由器处变为 0,该数据包将在不通知发送者的情况下被丢弃。

于 2012-05-04T14:40:02.267 回答