代码之家  ›  专栏  ›  技术社区  ›  KernelMode

使用twisted python侦听到服务器的连接时获取用户输入

  •  1
  • KernelMode  · 技术社区  · 10 年前

    我目前正在尝试使用Twisted Python进行一个项目,我的问题是我试图在使用listenTCP()监听连接的同时获取用户输入。我最初查了一下这个问题,发现了那个问题。StandardIO似乎是最有效的方法,因为我已经在使用Twisted了。我还看到了扭曲矩阵上的代码示例, stdin.py 还有 stdiodemo.py 然而,鉴于我需要从套接字中读取数据并在执行tcp任务时收集用户输入,因此我很难将示例代码应用于我的特定问题。

    我正在进行的项目要大得多,但小示例代码说明了我正在尝试做什么,并隔离了我遇到的问题。任何帮助我解决问题的人都非常感激。

    服务器.py

    from twisted.internet.protocol import Factory
    from twisted.protocols import basic
    from twisted.internet import reactor, protocol, stdio
    from Tkinter import *
    import os, sys
    
    class ServerProtocol(protocol.Protocol):
        def __init__(self, factory):
            self.factory = factory
            stdio.StandardIO(self)
    
        def connectionMade(self):
            self.factory.numConnections += 1
            self.factory.clients.append(self)
    
        def dataReceived(self, data):
            try:
                print 'receiving data'
                print data
            except Exception, e:
                print e
    
        def connectionLost(self, reason):
            self.factory.numConnections -= 1
            self.factory.clients.remove(self)
    
    class ServerFactory(Factory):
        numConnections = 0
        def buildProtocol(self, addr):
            return ServerProtocol(self)
    
    class StdioCommandLine(basic.LineReceiver):
        from os import linesep as delimiter
        def connectionMade(self):
            self.transport.write('>>> ')
        def lineReceived(self, line):
            self.sendLine('Echo: ' + line)
            self.transport.write('>>> ')
    
    reactor.listenTCP(9001, ServerFactory())
    stdio.StandardIO(StdioCommandLine())
    reactor.run()
    

    客户端.py

    from twisted.internet import reactor, protocol
    import os, time, sys
    import argparse
    
    class MessageClientProtocol(protocol.Protocol):
    
        def __init__(self, factory):
            self.factory = factory
    
        def connectionMade(self):
            self.sendMessage()
    
        def sendMessage(self):
            print 'sending message'
            try:
                self.transport.write('hello world')
            except e as Exception:
                print e
    
        def dataReceived(self, data):
            print 'received: ', data
            self.sendMessage()
    
    class MessageClientFactory(protocol.ClientFactory):
    
        def __init__(self, message):
            self.message = message
    
        def buildProtocol(self, addr):
            return MessageClientProtocol(self)
    
        def clientConnectionFailed(self, connector, reason):
            print 'Connection Failed: ', reason.getErrorMessage()
            reactor.stop()
    
        def clientConnectionLost(self, connector, reason):
            print 'Connection Lost: ', reason.getErrorMessage()
    
    reactor.connectTCP('192.168.1.70', 9001, MessageClientFactory('hello world - client'))
    reactor.run()
    

    此时,上述代码将返回一个Unhand Error,如下所示。这演示了如何使用stdin,然后将数据返回到stdout,并将导致错误的连接返回到客户端:

    python服务器.py

    >>>你好

    回声:你好

    >>>未处理的错误跟踪(最近一次调用的最后一次):

    文件 “/Library/Frameworks/Python.Frameworks/Versions/2.7/lib/python2.7/site-packages/twisted/Python/log.py”, 第84行,调用WithContext

    返回上下文。调用({ILogContext:newCtx},func,*args,**kw)

    文件 “/Library/Frameworks/Python.Frameworks/Versions/2.7/lib/python2.7/site-packages/twisted/Python/context.py”, 第118行,callWithContext返回 self.currentContext()。callWithContext(ctx,func,*args,**kw)

    文件 “/Library/Frameworks/Python.Frameworks/Versions/2.7/lib/python2.7/site-packages/twisted/Python/context.py”, 第81行,调用WithContext

    返回函数(*args,**kw)

    文件 “/Library/Frameworks/Python.Frameworks/Versions/2.7/lib/python2.7/site-packages/twisted/internet/selectreactor.py”, 第149行,在_doReadOrWrite中

    why=getattr(可选,方法)()

    ---在此捕获异常---

    文件 “/Library/Frameworks/Python.Frameworks/Versions/2.7/lib/python2.7/site-packages/twisted/internet/tcp.py”, 第1067行,在doRead中
    协议=s

    1 回复  |  直到 10 年前
        1
  •  0
  •   Manuel Jacob    10 年前

    您提供的跟踪似乎已被切断。我尝试在我的机器上运行代码,它显示了此跟踪:

    Traceback (most recent call last):
      File "/usr/lib/python2.7/site-packages/twisted/python/log.py", line 84, in callWithContext
        return context.call({ILogContext: newCtx}, func, *args, **kw)
      File "/usr/lib/python2.7/site-packages/twisted/python/context.py", line 118, in callWithContext
        return self.currentContext().callWithContext(ctx, func, *args, **kw)
      File "/usr/lib/python2.7/site-packages/twisted/python/context.py", line 81, in callWithContext
        return func(*args,**kw)
      File "/usr/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 597, in _doReadOrWrite
        why = selectable.doRead()
    --- <exception caught here> ---
      File "/usr/lib/python2.7/site-packages/twisted/internet/tcp.py", line 1067, in doRead
        protocol = self.factory.buildProtocol(self._buildAddr(addr))
      File "Server.py", line 30, in buildProtocol
        return ServerProtocol(self)
      File "Server.py", line 10, in __init__
        stdio.StandardIO(self)
      File "/usr/lib/python2.7/site-packages/twisted/internet/_posixstdio.py", line 42, in __init__
        self.protocol.makeConnection(self)
      File "/usr/lib/python2.7/site-packages/twisted/internet/protocol.py", line 490, in makeConnection
        self.connectionMade()
      File "Server.py", line 14, in connectionMade
        self.factory.clients.append(self)
    exceptions.AttributeError: ServerFactory instance has no attribute 'clients'
    

    从完整的追溯中可以很容易看出,工厂缺少 client 属性这可以修复,例如将其添加到您的 ServerFactory 类别:

    def __init__(self):
        self.clients = []