Twisted:在使用pyglet-twisted时,如何从EndPoint调用Deferred

1 投票
2 回答
946 浏览
提问于 2025-04-17 15:09

下面的代码来自Twisted的AMP文档(链接)。当你给d添加一个回调时,它会自动添加一个“协议”参数,并且当调用reactor.run()时,deferred会自动运行。

def connect():
    endpoint = TCP4ClientEndpoint(reactor, "127.0.0.1", 8750)
    factory = Factory()
    factory.protocol = AMP
    return endpoint.connect(factory)

d = connect()
def connected(protocol):
    return protocol.callRemote(
        RegisterUser,
        username=u'alice'
d.addCallback(connected)

reactor.run()

在我的代码中,其他部分完全一样,只是我在使用pyglet-twisted(链接)和cocos2d,所以我不能调用reactor.run(),因为反应器和应用程序是同时启动的。

如果我调用reactor.run(),会出现一个错误,提示反应器已经在运行。

如果不调用,deferred似乎也不会被触发。

我尝试用reactor.callLater和reactor.callWhenRunning来调用它,但这两个方法都需要一个参数。传入None是无效的。

所以我的问题是,如何在不调用reactor.run()的情况下让这个deferred运行。

谢谢!

2 个回答

1

经过进一步研究,我发现从 endpoint.connect() 返回的 deferred 没有被调用,是因为cocos2d里面的一个bug。

cocos.director 的底部,pyglet.app.event_loop 被用来处理导演的事件,这一行是 director.event = event_loop.event

这里需要改成使用 pygletreactoreventloop。所以上面的代码需要改成下面这样:

import pygletreactor
event_loop = pygletreactor.EventLoop()
director = Director()
director.event = event_loop.event
1

Twisted的很多功能在没有运行的反应器(reactor)的情况下是无法正常工作的。反应器负责处理输入输出(I/O)操作。你必须有一个正在运行的反应器,才能建立连接(无论你是使用端点对象还是其他API来实现)。

根据我的了解,pyglet集成的反应器并不会自动启动。必须有某个东西来调用它的run方法。你的问题暗示你没有调用这个方法,所以我很好奇到底是什么在调用它。

当我修改你的示例,使其完整可运行并添加错误报告时,像这样:

from pygletreactor import install
install()

from twisted.internet import reactor
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.internet.protocol import Factory
from twisted.protocols.amp import AMP
from twisted.python.log import err

def connect():
    endpoint = TCP4ClientEndpoint(reactor, "127.0.0.1", 8750)
    factory = Factory()
    factory.protocol = AMP
    return endpoint.connect(factory)

d = connect()
def connected(protocol):
    return protocol.callRemote(
        RegisterUser,
        username=u'alice')
d.addCallback(connected)
d.addErrback(err)

reactor.run()

那么我就得到了我预期的结果,也就是尝试连接然后失败(因为我没有在任何地方运行AMP服务器):

Unhandled Error
Traceback (most recent call last):
Failure: twisted.internet.error.ConnectionRefusedError: Connection was refused by other side: 111: Connection refused.

也许你可以把这个和你的完整程序进行对比,找出一个重要的区别。

撰写回答