客户端:
#!/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()
SERVER:
#!/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()
ERROR:
exceptions.TypeError: buildProtocol() takes exactly 2 arguments (3 given)
问题:
如何让EchoClient
中的CLIENT
类接受参数并分配实例变量(例如上面EchoClient
构造函数中的arg)?如下所述,之前建议我覆盖buildProtocol
函数,但我这样做的尝试导致我出现上述错误。我不确定从哪里开始。我想我的问题可以归结为:如何将实例变量添加到协议中?
答案 0 :(得分:7)
def buildProtocol(self, address):
proto = protocol.ClientFactory.buildProtocol(self, address, 12)
也就是说,您将覆盖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
事实上,整个ProtocolFactory业务是支持这种用途;但要注意; Protocol
的许多实例将共享其工厂的单个实例;使用工厂进行配置,但在协议中管理状态。
标准的协议/工厂实现方式当然不可能满足您的需求,这也是合理的,只要您完全实现IProtocol
和IProtocolFactory
接口即可。存在基类是因为它们为您处理大多数情况,而不是因为它们是唯一可能的实现。
答案 1 :(得分:1)
从您的问题中不清楚完全您的尝试究竟错误是什么,但无论如何您必须执行两个步骤:
EchoClient
的构造函数接受您需要的任何参数,并初始化您需要它初始化的任何字段。buildProtocol
方法,以便为协议提供这些参数。