扭曲的回调循环阻止接收更多数据

Twisted callback loop blocking further data from being recieved

当回调循环在 Twisted 中 运行ning 时,我的印象是 reactor 仍然能够 send/receive 来自服务器的数据,因为它能够运行 'between' 回调。但是,当我 运行 下面的脚本时,它完全忽略了 self.transport.write() 行。服务器只是 Twisted 在其网站上的基本回显服务器。

from twisted.internet import reactor, protocol
from twisted.internet.defer import Deferred


class EchoClient(protocol.Protocol):

    deferred = Deferred()

    def connectionMade(self):
        self.deferred.addCallback(self.doThing)
        self.deferred.callback(0)

    def doThing(self, _):
        print 'xxx'
        self.transport.write('Hello, world!')
        self.deferred.addCallback(self.doThing)

    def dataReceived(self, data):
        "As soon as any data is received, write it back."
        print "Server said:", data
        self.transport.loseConnection()


class EchoFactory(protocol.ClientFactory):

    protocol = EchoClient


def main():
    f = EchoFactory()
    reactor.connectTCP('192.168.0.7', 8000, f) # Correctly connected to my server
    reactor.run()

if __name__ == '__main__':
    main()

我预计会打印一个或什至几个 'xxx's,然后服务器将 'Hello, world!' 的回显发送回给我,然后再发送更多 'xxx's。相反,我得到的是 'xxx' 的无限滚动,甚至没有尝试将 'Hello, world!' 发送到服务器。我是什么missing/misunderstanding?

问题是您的示例从不让主循环 运行。

建立连接后,您向 self.deferred 添加回调 - 我不确定 self.deferred 应该代表什么操作,但显然没有任何用处。

然后你立即(同步)回拨self.deferred。这会立即执行 doThing,它会调用 self.transport.write。这会在主循环下一个 运行s 时将一些字节添加到要发送的传出缓冲区。然后,在该回调中,您立即(同步)向 self.deferred 添加另一个回调,一旦当前回调完成,该回调将 运行 。所以我们进入 doThing,它调用 self.transport.write。我们还没有写任何东西,更不用说读取任何东西来传递给 dataReceived,因为我们还没有回到主循环。但是我们向 Deferred 添加了另一个回调。再次调用 doThing

这会一直持续下去,在缓冲不断增加的传出流量时在传输上分配无限量的内存,但绝不允许程序从 connectionMade return,使它回到主循环,等待可写性和可读性事件。

我不知道如何修复此程序,因为不清楚您尝试做什么,但无论如何,这不是办法:).