2011-10-26 73 views
3

我有一個類繼承twisted.internet.protocol.DatagramProtocol類。在我的startProtocol()實現中,我調用startWriting(),以便每次我可以寫入時通知套接字而不會阻塞。兩個問題:UDP流量控制與Python Twisted

  1. 什麼樣的方法將調用一次套接字將變爲可寫?
  2. 如果需要在特定的時間間隔上調用startWriting()方法來限制外出UDP帶寬爲特定的數據報/秒數,我應該如何調用startWriting()方法?

回答

2

糟糕。我想我可能已經在另一個線程中回答了您的問題,並且讓您相信Twisted中的UDP流量控制支持比實際上更強大一些。儘管如此,你可以得到你需要做的事情...

1.哪種方法將Twisted調用一次套接字將變成可寫?

不幸的是,Twisted中的UDP協議在可寫性方面沒有得到監控,前提是UDP總是可能失敗,所以它永遠不應該升起EWOULDBLOCK。 (除了實際上,它有時和我剛剛在回答這個問題時重新發現的this is a bug in Twisted這隻發生在Twisted以比本地線速度更快的速度發送UDP時,這需要非常快的應用程序和非常慢的網絡。)

作爲解決方法,您的應用程序可以簡單地捕獲EWOULDBLOCK。對於任何其他協議,此類解決方案可能構成嚴重問題,但對於UDP,您必須準備好丟失任何傳出數據包,因此無論如何您都需要帶內控制流程機制。

通過review process幫助我們獲得that bug始終是一種選擇。

如果你想獲得真的花哨,您可以編寫自己的替代udp.Port(自行實施IFileDescriptor),而不是寫一個UDP協議,並覆蓋doReaddoWrite(被稱爲當標的插座是可讀和分別可寫)。這將爲您提供完美的寫入級流量控制,但可能不是必需的,因爲UDP有時會丟棄數據包,並且在網絡上無法正確處理「ICMP源熄滅」消息(將默認的防火牆配置爲塊ICMP就會阻塞),丟包是你的流量控制信息的來源只有。我並不是說你不應該在Twisted中糾正這個錯誤,但是這個UDP世界中的生活事實可能是沒人願意這麼做的原因。

2.如果需要在特定時間間隔上調用startWriting()方法以限制傳出UDP帶寬爲特定數據報/秒數,我應該如何調用startWriting()方法?

由於本答案的第1部分中描述的限制,UDP傳輸沒有有用的startWriting方法。

但是,startWriting/stopWriting不是真的正確的方式來限制你的出站UDP帶寬無論如何。

在通過適當的調度機制調度所述調用之後,在適當的時間簡單地呼叫self.transport.write(...)。例如,設計用於以合適的間隔爲發送聲音樣本調用用於RTP媒體流的UDP發送。但你也可以直接計算自己的延遲並使用callLater。在任何情況下,如果您需要對通過UDP傳輸排隊的傳出數據進行任何重新傳輸,您可能需要保留某種隊列機制,因此只需彈出

如果您需要執行入站流量控制,UDP傳輸仍然支持,很好,stopReadingstartReading

希望這個答案是有幫助的,如果我以前誤導了你關於Twisted在這個領域的能力,對不起!

+1

感謝您的回答。我使用LoopingCall實現了UDP流量控制。 Looping Call的問題是,當UDP數據包很小(50字節)時,它不能推送超過300KBps。在此測試期間,CPU沒有被刷新。當這個LoopingCall回調被調用時,也許我應該嘗試在一個循環中執行write()...... –

+0

你說'LoopingCall'具有0超時只會在硬件上每秒推送〜6000個UDP數據包,但不會* *最大限度地減少你的CPU?天真的'callLater'循環怎麼樣? – Glyph

+1

我剛剛在一個緊密的無限循環中實現了UDP發送,並且能夠最大限度地利用CPU,同時仍然以50字節的數據包實現8MBps。仍然不是很多,但比LoopingCall好20倍。這裏最大的瓶頸很可能是Python。如果我可以用一個sendto()調用發送多個數據報,那將會很好。 –