在Twisted中正确访问协议的传输方式是什么?

0 投票
2 回答
845 浏览
提问于 2025-04-18 04:31

在这个TCP客户端的例子中:

from twisted.internet import reactor, protocol


# a client protocol

class EchoClient(protocol.Protocol):
    """Once connected, send a message, then print the result."""

    def connectionMade(self):
        self.transport.write("hello, world!")

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

    def connectionLost(self, reason):
        print "connection lost"

class EchoFactory(protocol.ClientFactory):
    protocol = EchoClient

    def clientConnectionFailed(self, connector, reason):
        print "Connection failed - goodbye!"
        reactor.stop()

    def clientConnectionLost(self, connector, reason):
        print "Connection lost - goodbye!"
        reactor.stop()


# this connects the protocol to a server runing on port 8000
def main():
    f = EchoFactory()
    reactor.connectTCP("localhost", 8000, f)
    reactor.run()

# this only runs if the module was *not* imported
if __name__ == '__main__':
    main()

我有一个定期需要向服务器发送数据的任务。这个任务的所有逻辑都在协议和工厂之外。把f传来传去,然后用f.protocol.transport.write("Something?")来发送数据,这样做算不算不太好呢?

2 个回答

0

我也是刚接触Twisted这个框架,所以我的看法仅供参考,但我觉得这是可以接受的做法。

你可以看看我在下面这个StackOverflow上的回答,里面有个例子讲了怎么把Twisted的各个部分连接起来:Twisted中的持久连接。(顺便提一下,那篇回答也提到了定时任务……)

编辑

哦,等等。你里面有一个工厂。

这个工厂每次有连接时都会创建一个新的协议实例,所以你的f.protocol.transport.write是行不通的(因为protocol指向的是类,而不是一个已经连接的实例)。你可以试试我在持久连接问题中的代码示例,我在工厂里创建了一个连接列表(就是self.clients),通过这个结构你可以遍历连接列表,使用不同连接的.write方法。

2

你可以重新组织你的代码,利用一些比较新的接口,这样就不用在工厂里做额外的工作来实现你的目标。Mike Lutz的回答是完全正确的,这也是我以前建议大家在没有端点的时候使用的方法。现在有了端点,我建议大家使用这些端点。

端点接口让你可以写一个看起来更像这样的主函数:

def main():
    e = HostnameEndpoint(reactor, "localhost", 8000)
    f = EchoFactory()
    d = e.connect(f)
    d.addCallback(connected)
    return d

def connected(protocol):
    # protocol is an instance of EchoClient and is connected
    return LoopingCall(doStuff, protocol).start(3)

你也可以考虑把这个改成使用 twisted.internet.task.react,这样可以帮你处理一些反应器的管理工作。

撰写回答