在Python中编写可靠的完全有序组播系统

5 投票
3 回答
3339 浏览
提问于 2025-04-11 09:31

我需要从头开始用Python写一个可靠的、完全有序的多播系统。不能使用任何外部库,但可以使用一个中央的排序器。

看起来有两种直接的方法:

  1. 写一个高效的系统,为每个多播的消息附上一个唯一的ID,让排序器为它收到的消息ID多播序列号,并且互相发送确认和拒绝确认。
  2. 写一个效率不高的洪泛系统,每个多播者只需将收到的每条消息重新发送一次(除非这条消息是由它自己发送的)。

我可以选择第二种方法,而且我倾向于这样做。

目前我正在使用UDP进行多播(这似乎是唯一的选择),但这意味着有些消息可能会丢失。因此,我需要能够唯一识别每条发送的UDP消息,以便根据第二种方法重新发送。那我是否真的应该生成唯一的编号(比如使用发送者地址和一个计数器)并把它们放进每一条发送的UDP消息里呢?我该怎么做呢?还有,如何在Python中接收单条UDP消息,而不是一串数据(也就是 socket.recv)呢?

3 个回答

0

在我看来,你应该选择一个现成的可靠的UDP协议。有几个可以选择的,看看这个StackOverflow的问题:当你需要可靠的UDP时,你会用什么?

我个人喜欢并使用MoldUDP,这是纳斯达克的ITCH市场数据传输所用的协议。

1

你选择的方式很大程度上取决于你发送的数据类型、网络的规模以及你发送的数据量。特别是,这还要看你每个节点连接了多少个目标。

如果你希望每个节点能连接很多目标,并且发送大量数据,那么你可能会发现,在每个数据包中添加确认(ACK)或否认(NAK)的开销会影响你的传输速度,尤其是当你还需要重新发送数据时。

正如Frank Szczerba所说,多媒体数据的一个好处是它能从丢失的数据包中恢复过来。如果你能控制发送的数据,应该尽量设计数据内容,减少丢包的可能性。

如果你发送的数据不能接受丢包,并且你想要充分利用网络,那么也许使用UDP协议就不是最佳选择。实现一系列TCP代理(每个节点将数据单独发送给所有其他连接的节点,类似于你提到的洪泛思想)会是一个更可靠的方式。

说到这里,你有没有考虑过使用真正的多播来解决这个问题呢?


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

4

洪水式传输方法可能会让糟糕的情况变得更糟。如果因为网络负载过高而导致消息丢失,那么让每个节点重新发送每条消息只会加重这个问题。

选择最佳的方法取决于你发送的数据类型。例如:

  1. 多媒体数据:不需要重发,丢失的数据包就像丢失了一帧画面,反正下一帧到的时候也不会在意。
  2. 固定周期的数据:接收节点会保持一个计时器,每次收到更新时都会重置这个计时器。如果时间到了,它就会向主节点请求缺失的更新。重发可以单独发送给请求的节点。

如果以上两种情况都不适用(每个数据包都必须被每个节点接收,并且数据包的到达时间不可预测,接收者无法自己检测丢失的数据包),那么你可以考虑以下选项:

  1. 每个节点对每个数据包都要明确确认(ACK)。发送者会重发任何没有被确认的数据包。
  2. 基于TCP的网格方法,每个节点手动将接收到的数据包重复发送给邻近的节点,依靠TCP机制来确保数据的送达。

你也可以依赖接收者在收到一个序列号更大的数据包时注意到丢失的数据包,但这要求发送者在至少发送一个额外的数据包之前保留这个数据包。要求正向确认(ACK)会更可靠(也更容易证明)。

撰写回答