2012-04-28 101 views
2

我試圖編寫一個簡單的Echo客戶端在扭曲,發送鍵盤輸入到服務器,並由用戶輸入'q'自己終止。總之,我只是想修改在this page上找到的簡單回聲客戶端(和變體)。沒有什麼性感,只是基本。簡單的扭曲回聲客戶端

我很苦惱與非常基本的事件循環。看起來我無法在迴路內啓動/停止反應堆,因爲停止的反應堆不能爲restarted。如果我不停止反應堆,那麼我將永遠不會進入下一行獲得鍵盤輸入。

任何幫助讓我的回聲客戶端工作將不勝感激。

from twisted.internet.protocol import ClientFactory 
from twisted.protocols.basic import LineReceiver 
from twisted.internet import reactor 

class EchoClient(LineReceiver): 
    end="Bye-bye!" 
    def connectionMade(self): 
     #only write and end transmission if the message isn't empty 
     if len(self.factory.message) > 0: 
      self.sendLine(self.factory.message) 
      self.sendLine(self.end) 
     else: 
     #Else just terminate the connection 
      self.transport.loseConnection() 

    def lineReceived(self, line): 
     print "receive:", line 
     if line==self.end: 
      self.transport.loseConnection() 

class EchoClientFactory(ClientFactory): 
    message = "" 

    def buildProtocol(self, address): 
     p = EchoClient() 
     p.factory = self 
     return p 

    def clientConnectionFailed(self, connector, reason): 
     reactor.stop() 

    def clientConnectionLost(self, connector, reason): 
     reactor.stop() 

def main(): 

    s = raw_input('Text to send (''q'' to terminate): ') 
    while s != 'q': 
     factory = EchoClientFactory() 
     factory.message = s 
     reactor.connectTCP('localhost', 8000, factory) 

     #This is bad because reactor cannot be restarted once it's been stopped 
     reactor.run() 

     s = raw_input('Text to send(''q'' to terminate): ') 

if __name__ == '__main__': 
    main() 
+0

可能重複的[python扭曲stdio多個連接到服務器與交互命令提示符](http://stackoverflow.com/questions/2311844/python-twisted-stdio-multiple-connections-to-a-server -with-a-command-prompt-for) – 2012-04-28 12:41:19

+0

這不是真的重複,jbreicis提供的答案遠遠好於在那裏提供的答案。 – CadentOrange 2012-04-28 13:47:02

+0

我的回答對於特定的任務並不好。隨着我的回答,我試圖更多地說明如何使傳統的阻止代碼兼容twisted.However - deferToThread是最簡單和最醜陋的方式。 Usualy你應該能夠找到「原生」扭曲的替代品。至於線路輸入,扭曲的示例部分提供了更好的扭曲本地方法http://twistedmatrix.com/trac/browser/trunk/doc/core/examples/stdin.py – jbreicis 2012-04-28 13:59:05

回答

3

作爲一個經驗法則 - 有非常罕見的情況下,您將要重新啓動或停止反應器,除非你是終止程序alltogeather。如果你遇到一段會導致阻塞的代碼數據庫訪問,長時間計算,或者在你的情況下raw_input,你必須:找到一個扭曲的替代(數據庫的情況下twisted.enterprise.adabi)或扭曲兼容。 '解鎖'你的代碼最簡單的方法是通過使用twisted.internet.threads中的deferToThread將阻塞位移入線程。 考慮這個例子:

from twisted.internet.threads import deferToThread as __deferToThread 
from twisted.internet import reactor 

def mmprint(s): 
    print(s) 

class TwistedRAWInput(object): 
    def start(self,callable,terminator): 
     self.callable=callable 
     self.terminator=terminator 
     self.startReceiving() 
    def startReceiving(self,s=''): 
     if s!=self.terminator: 
      self.callable(s) 
      __deferToThread(raw_input,':').addCallback(self.startReceiving) 


tri = TwistedRAWInput() 
reactor.callWhenRunning(tri.start,mmprint,'q') 
reactor.run() 

你就永遠不會停止反應器,如將的raw_input的外螺紋發生,在每一個新行callbacking推遲。

+0

感謝您的回答。它看起來很有效,我開始明白爲什麼人們說Twisted的學習曲線非常陡峭!我無法自己弄清楚這一點。 – CadentOrange 2012-04-28 12:47:52

+0

它並不是很陡峭。它基本上只是一個非常陡峭的凹凸來獲得這個概念;之後,它是最好的框架。 – jbreicis 2012-04-28 13:21:25