5

我必须用 Python 从头开始​​编写一个可靠的、完全有序的多播系统。我不能使用任何外部库。我被允许使用中央音序器。

似乎有两种直接的方法:

  1. 编写一个高效的系统,为每个多播消息附加一个唯一的 id,为其接收到的消息 id 具有定序器多播序列号,并来回发送 ACK 和 NACK。
  2. 编写一个低效的泛洪系统,其中每个多播器只需重新​​发送它接收到的每条消息一次(除非它是由那个特定的多播器发送的。)

我被允许使用第二个选项,并且倾向于这样做。

我目前正在多播 UDP 消息(这似乎是唯一的选择),但这意味着某些消息可能会丢失。这意味着我必须能够唯一标识每个发送的 UDP 消息,以便可以根据 #2 重新发送它。我真的应该生成唯一的数字(例如使用发件人地址和计数器)并将它们打包到每个发送的 UDP 消息中吗?我该怎么做呢?以及如何在 Python 中接收单个 UDP 消息,而不是数据流(即socket.recv)?

4

3 回答 3

4

泛滥的方法可能会导致糟糕的情况变得更糟。如果消息由于高网络负载而被丢弃,让每个节点重新发送每条消息只会使情况变得更糟。

采取的最佳方法取决于您发送的数据的性质。例如:

  1. 多媒体数据:不重试,丢弃的数据包是丢弃的帧,无论如何下一帧何时到达都无关紧要。
  2. 固定周期数据:接收节点保持一个计时器,每次收到更新时都会重置该计时器。如果时间到期,它会向主节点请求丢失的更新。重试可以单播到请求节点。

如果这两种情况都不适用(每个节点都必须接收每个数据包,并且数据包时间不可预测,因此接收者无法自行检测丢失的数据包),那么您的选项包括:

  1. 每个数据包的每个节点的显式 ACK。发送方重试(单播)任何未确认的数据包。
  2. 基于 TCP 的网格方法,其中每个节点手动将接收到的数据包重复到相邻节点,依靠 TCP 机制来确保传递。

您可能会依赖接收者在收到具有较晚序列号的数据包时注意到丢失的数据包,但这要求发送者保留数据包,直到至少发送一个额外的数据包。要求肯定的 ACK 更可靠(并且可证明)。

于 2008-10-06T21:32:46.827 回答
1

您采用的方法将在很大程度上取决于您发送的数据的性质、网络的规模以及您发送的数据量。特别是,它将取决于每个节点连接到的目标数量。

如果您希望这可以扩展到每个节点的大量目标和大量数据,那么您可能会发现向每个数据包添加 ACK/NAK 的开销足以不利地限制您的吞吐量,特别是当您将重新传输添加到混合中。

正如 Frank Szczerba 所说,多媒体数据的好处是能够从丢失的数据包中恢复。如果您对发送的数据有任何控制权,则应尝试设计有效负载,以最大程度地减少对丢弃数据包的敏感性。

如果您发送的数据不能容忍丢弃的数据包,并且您正在尝试扩展到网络的高利用率,那么 udp 可能不是最好的协议。实现一系列 tcp 代理(其中每个节点向所有其他连接的节点重新传输、单播 - 类似于您的泛洪想法)将是一种更可靠的机制。

综上所述,您是否考虑过为此应用程序使用真正的多播?


刚刚看到“作业”标签......这些建议可能不适合家庭作业问题。

于 2008-10-06T22:42:25.563 回答
0

恕我直言,您应该选择现有的可靠 UDP 协议。有几个你可以选择,看看这个 SO 问题:当你需要可靠的 UDP 时,你使用什么?

我个人喜欢并使用MoldUDP,这是 Nasdaq 的 ITCH 市场数据馈送所使用的协议。

于 2021-06-25T15:45:59.407 回答