2012-04-28 99 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