如何在Twisted的Protocol方法中修改Controller类的nodes变量?
嘿,我懂你现在的困扰——想把客户端IP加到Controller的nodes列表里,但在MyServerProtocol的connectionMade方法里死活拿不到Controller的引用对吧?这是因为你的Protocol和Controller之间还没建立关联,咱们一步步来搞定这个问题:
问题根源
你的MyServerProtocol实例是由ControllerFactory创建的,但Factory和Controller之间完全没有联系,所以Protocol自然找不到Controller的nodes列表。咱们需要把Controller的引用传递给Factory,再由Factory转交给Protocol。
修改步骤
把nodes改成Controller的实例变量
先建议把nodes从类变量改成实例变量,这样每个Controller实例都有自己独立的节点列表,避免多个实例共享数据的意外问题:# controller.py class Controller(object): def __init__(self, port): self.nodes = [] # 改为实例变量,每个Controller拥有自己的节点列表 ss = SimpleServer(port, self) # 把Controller自身传给SimpleServer让SimpleServer接收Controller的引用
修改SimpleServer的初始化方法,让它把Controller的引用传给Factory:# server.py class SimpleServer(): def __init__(self, port, controller): # 将controller实例传入ControllerFactory reactor.listenTCP(port, ControllerFactory(controller)) print(f'server listening on {port}') reactor.run()修改ControllerFactory,保存并传递Controller引用
在Factory里存储Controller的引用,创建Protocol时把这个引用传递过去:# server.py class ControllerFactory(Factory): def __init__(self, controller): self.controller = controller # 保存Controller的引用 def buildProtocol(self, addr): proto = MyServerProtocol() proto.controller = self.controller # 把Controller引用传给Protocol return proto在connectionMade中操作Controller的nodes列表
现在Protocol已经拿到了Controller的引用,就可以顺利添加客户端IP了:# server.py class MyServerProtocol(Protocol): def connectionMade(self): peer = self.transport.getPeer() # 把客户端IP(带端口)添加到nodes列表 self.controller.nodes.append(f"{peer.host}:{peer.port}") print(f"Client {peer.host}:{peer.port} connected, added to nodes list")
这样修改之后,每次客户端连接时,它的IP地址就会被正确添加到Controller的nodes列表里了。
另外提一句,self.transport.getPeer()返回的是Twisted的IPv4Address/IPv6Address对象,如果你只需要纯IP字符串,直接用peer.host就可以啦。
内容的提问来源于stack exchange,提问作者Farah Zein

