我有一个从类继承的twisted.internet.protocol.DatagramProtocol
类。在我的startProtocol()
实现中,我调用startWriting()
了 ,因此每次我可以在不阻塞的情况下写入它时都会通知套接字。两个问题:
- 一旦 socket 变为可写状态,twisted 会调用哪个方法?
startWriting()
如果需要在特定的时间间隔内调用方法以将传出的 UDP 带宽限制为特定的数据报/秒数量,我应该如何调用方法?
我有一个从类继承的twisted.internet.protocol.DatagramProtocol
类。在我的startProtocol()
实现中,我调用startWriting()
了 ,因此每次我可以在不阻塞的情况下写入它时都会通知套接字。两个问题:
startWriting()
如果需要在特定的时间间隔内调用方法以将传出的 UDP 带宽限制为特定的数据报/秒数量,我应该如何调用方法?哎呀。我想我可能已经在另一个线程中回答了您的问题,并让您相信 Twisted 中的 UDP 流量控制支持比实际情况更强大。尽管如此,你可以完成你需要做的事情......
不幸的是,Twisted 中的 UDP 协议没有被监控可写性,前提是 UDP 总是会失败,因此它不应该引发EWOULDBLOCK
. (实际上,有时确实如此,这是我刚刚在回答这个问题时重新发现的 Twisted 中的一个错误。只有当 Twisted 以比本地线速更快的速度发送 UDP 时才会发生这种情况,这需要非常快的应用程序和非常网速慢。)
作为一种解决方法,您的应用程序可以简单地捕获EWOULDBLOCK
. 对于任何其他协议,这种类型的解决方法可能会构成一个严重的问题,但在 UDP 的情况下,您已经准备好丢失任何传出的数据包,因此无论如何您都需要一个带内控制流机制。
如果您想变得真正花哨,您可以编写自己的替代方案udp.Port
(通过实现IFileDescriptor
自己)而不是编写 UDP 协议,并覆盖doRead
and doWrite
(分别在底层套接字可读和可写时调用)。这将为您提供完美的写入级别流量控制,但可能不是必需的,因为 UDP 有时只会丢弃您的数据包,并且在无法正确处理“ICMP 源淬火”消息的网络上(哑防火墙配置为阻止 ICMP 只会阻止),丢弃的数据包是你唯一的流量控制信息的来源。我并不是说你不应该真正修复 Twisted 中的这个错误,但是 UDP 世界中的这一事实可能是没有人费心这样做的原因。
由于此答案第 1 部分中描述的限制,UDP 传输没有有用的startWriting
方法。
但是,startWriting
/stopWriting
无论如何都不是限制传出 UDP 带宽的正确方法。
self.transport.write(...)
在通过适当的调度机制安排所述调用之后, 只需在适当的时间调用。LoopingCall
例如,它旨在以适当的间隔为 RTP 媒体流调用 UDP 发送,以传输声音样本。但是您也可以只计算自己的延迟并直接使用callLater。在任何情况下,如果您需要重新传输排队等待通过 UDP 传输的传出数据,您可能需要保留某种队列机制,所以只需弹出
如果您需要进行入站流量控制,UDP 传输仍然可以很好地支持它,使用stopReading
和startReading
.
希望这个答案对您有所帮助,如果我之前在 Twisted 在这方面的能力方面误导了您,我们深表歉意!