3

我有一个从类继承的twisted.internet.protocol.DatagramProtocol类。在我的startProtocol()实现中,我调用startWriting()了 ,因此每次我可以在不阻塞的情况下写入它时都会通知套接字。两个问题:

  1. 一旦 socket 变为可写状态,twisted 会调用哪个方法?
  2. startWriting()如果需要在特定的时间间隔内调用方法以将传出的 UDP 带宽限制为特定的数据报/秒数量,我应该如何调用方法?
4

1 回答 1

2

哎呀。我想我可能已经在另一个线程中回答了您的问题,并让您相信 Twisted 中的 UDP 流量控制支持比实际情况更强大。尽管如此,你可以完成你需要做的事情......

1. 一旦 socket 变为可写,Twisted 会调用哪个方法?

不幸的是,Twisted 中的 UDP 协议没有被监控可写性,前提是 UDP 总是会失败,因此它不应该引发EWOULDBLOCK. (实际上,有时确实如此,这是我刚刚在回答这个问题时重新发现的 Twisted 中的一个错误。只有当 Twisted 以比本地线速更快的速度发送 UDP 时才会发生这种情况,这需要非常快的应用程序和非常网速慢。)

作为一种解决方法,您的应用程序可以简单地捕获EWOULDBLOCK. 对于任何其他协议,这种类型的解决方法可能会构成一个严重的问题,但在 UDP 的情况下,您已经准备好丢失任何传出的数据包,因此无论如何您都需要一个带内控制流机制。

帮助我们通过审查过程解决该错误始终也是一种选择。

如果您想变得真正花哨,您可以编写自己的替代方案udp.Port(通过实现IFileDescriptor自己)而不是编写 UDP 协议,并覆盖doReadand doWrite(分别在底层套接字可读和可写时调用)。这将为您提供完美的写入级别流量控制,但可能不是必需的,因为 UDP 有时只会丢弃您的数据包,并且在无法正确处理“ICMP 源淬火”消息的网络上(哑防火墙配置为阻止 ICMP 只会阻止),丢弃的数据包是你唯一的流量控制信息的来源。我并不是说你不应该真正修复 Twisted 中的这个错误,但是 UDP 世界中的这一事实可能是没有人费心这样做的原因。

2. 如果需要在特定的时间间隔内调用 startWriting() 方法以将传出的 UDP 带宽限制为特定的数据报/秒数量,我应该如何调用它?

由于此答案第 1 部分中描述的限制,UDP 传输没有有用的startWriting方法。

但是,startWriting/stopWriting无论如何都不是限制传出 UDP 带宽的正确方法。

self.transport.write(...)在通过适当的调度机制安排所述调用之后, 只需在适当的时间调用。LoopingCall例如,它旨在以适当的间隔为 RTP 媒体流调用 UDP 发送,以传输声音样本。但是您也可以只计算自己的延迟并直接使用callLater。在任何情况下,如果您需要重新传输排队等待通过 UDP 传输的传出数据,您可能需要保留某种队列机制,所以只需弹出

如果您需要进行入站流量控制,UDP 传输仍然可以很好地支持它,使用stopReadingstartReading.

希望这个答案对您有所帮助,如果我之前在 Twisted 在这方面的能力方面误导了您,我们深表歉意!

于 2011-10-28T12:20:47.173 回答