扭曲协议实例变量?

rar*_*ify 2 python oop networking twisted

客户:

#!/usr/bin/env python

from twisted.internet import reactor, protocol

class EchoClient(protocol.Protocol):
    def __init__(self, arg):
        self.arg = arg

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

    def dataReceived(self, data):
        print "Server said:", data
        self.transport.loseConnection()

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

class EchoFactory(protocol.ClientFactory):
    protocol = EchoClient

    def buildProtocol(self, address):
        proto = protocol.ClientFactory.buildProtocol(self, address, 12)
        self.connectedProtocol = proto
        return proto

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

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

def main():
    f = EchoFactory()
    reactor.connectTCP("localhost", 8000, f)
    reactor.run()

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

服务器:

#!/usr/bin/env python

from twisted.internet import reactor, protocol
from twisted.application import service, internet

class Echo(protocol.Protocol):
    def dataReceived(self, data):
        self.transport.write(data)

def main():
    factory = protocol.ServerFactory()
    factory.protocol = Echo
    reactor.listenTCP(8000,factory)
    reactor.run()

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

错误:

exceptions.TypeError: buildProtocol() takes exactly 2 arguments (3 given)
Run Code Online (Sandbox Code Playgroud)

题:

如何EchoClientCLIENT接受参数和分配实例变量(例如EchoClient上面的构造函数中的arg )中获取类?如下所述,之前建议我覆盖该buildProtocol功能,但我这样做的尝试导致我出现上述错误.我不确定从哪里开始.我想我的问题可以概括为:如何将实例变量添加到协议中?

Sin*_*ion 7

你写了:

def buildProtocol(self, address):
    proto = protocol.ClientFactory.buildProtocol(self, address, 12)
Run Code Online (Sandbox Code Playgroud)

也就是说,您要覆盖ClientFactory.buildProtocol并使用与其知道如何处理的签名不同的签名调用父类.

将数据从工厂传递到客户端只是有点棘手.你可以提供任何__init__你想要的工厂,但twisted会创建IProtocol自己的实例.幸运的是,factory一旦准备就绪,大多数工厂都会将自己分配给协议的属性:

class MyClientProtocol(protocol.Protocol):
    def connectionMade(self):
        # use self.factory here:
        self.transport.write(self.factory.arg)

class MyClientFactory(protocol.ClientFactory):
    protocol = MyClientProtocol

    def __init__(self, arg):
        self.arg = arg
Run Code Online (Sandbox Code Playgroud)

事实上,整个ProtocolFactory业务是支持这种用途; 但要注意; 许多实例Protocol将分享他们工厂的单个实例; 使用工厂进行配置,但管理协议中的状态.

标准的协议/工厂实现方式可能不适合您的需求,这也是合理的,只要您完全实现IProtocolIProtocolFactory接口.存在基类是因为它们为您处理大多数情况,而不是因为它们是唯一可能的实现.