如何从扭曲的协议方法(如 ConnectionMade)修改变量
How to modify variables from twisted Protocol methodes such as ConnectionMade
我是 python 的新手,对 Twisted 了解更多,如果标题不够清楚,我深表歉意,但我会尽力描述我的问题。
我想在我的应用程序中分离逻辑和网络部分,所以我有 2 个 类 Controller 和 SimpleServer,我在 Controller 中有一个名为 nodes 的变量,我想通过添加客户端 Ip 来更新它每个连接,对于 python 专家来说可能是显而易见的,但我无法理解。请看看我的代码。我评论了我卡住的那一行。
感谢您的帮助
controller.py
class Controller(object):
nodes = []
def __init__(self, port):
ss= SimpleServer(port)
server.py
class MyServerProtocol(Protocol):
def connectionMade(self):
#ctrl.nodeList.append(self.transport.getPeer()) #this is what I want to do
class ControllerFactory(Factory):
def buildProtocol(self, addr):
return MyServerProtocol()
class SimpleServer():
def __init__(self, port):
reactor.listenTCP(port, ControllerFactory()) #@UndefinedVariable
print 'server listening on %d' %port
reactor.run() #@UndefinedVariable
主程序
if __name__ == '__main__':
port = 9123
ctrl = Controller(port)
客户端
class myClientProtocol(Protocol):
def dataReceived(self, data):
print ("data received", data)
class myClientFactory(ClientFactory):
def buildProtocol(self, addr):
print 'Connected.'
return myClientProtocol()
if __name__ == '__main__':
print "CLIENT : connecting to : [ %s ] on [ %s ]\n" %(IP,PORT)
reactor.connectTCP('127.0.0.1',9123, myClientFactory()) #@UndefinedVariable
reactor.run() #@UndefinedVariable
您只需要引用正确的对象。
就像您需要对反应器的引用一样,您导入了 twisted.internet.reactor
以便您可以调用 运行 方法。
controller.py
class Controller(object):
def __init__(self, port):
# Don't set self.nodes as a class attribute or it is shared across all instances
self.nodes = []
# Don't just use a local for SimpleServer, keep a reference on an attribute. Also, pass the controller instance in.
self.ss = SimpleServer(port, self)
server.py
class MyServerProtocol(Protocol):
def connectionMade(self):
# Get the reference to the Controller instance.
ctrl = self.factory.server.controller
# Use it.
ctrl.nodeList.append(self.transport.getPeer())
class ControllerFactory(Factory):
# Set this class attribute so the inherited buildProtocol does the work for us, including setting the factory attribute.
protocol = MyServerProtocol
def __init__(self, server):
# Save a reference to the given server as an attribute on the instance.
self.server = server
Factory.__init__(self)
class SimpleServer():
def __init__(self, port, controller):
self.controller = controller
# Pass a reference to the SimpleServer instance to the ControllerFactory
reactor.listenTCP(port, ControllerFactory(self))
print 'server listening on %d' %port
reactor.run()
主程序
if __name__ == '__main__':
port = 9123
ctrl = Controller(port)
客户端
class myClientProtocol(Protocol):
def dataReceived(self, data):
print ("data received", data)
class myClientFactory(ClientFactory):
def buildProtocol(self, addr):
print 'Connected.'
return myClientProtocol()
if __name__ == '__main__':
print "CLIENT : connecting to : [ %s ] on [ %s ]\n" %(IP,PORT)
reactor.connectTCP('127.0.0.1',9123, myClientFactory()) #@UndefinedVariable
reactor.run() #@UndefinedVariable
我做了我能看到的最小的一组更改来演示解决方案。我还没有测试结果代码。希望您能看到我所做的是引用代码的一部分所具有的对象,并将它们传递给需要它们的代码的其他部分。这通常采用将参数传递给函数(初始化程序、方法等)和设置对象属性(通常是 self 所指的任何内容)的形式。
我没有尝试提高代码的可维护性或更正任何令人担忧的模式。此代码仍然不是理想软件的模型,但它至少应该让您将一个值附加到您希望它附加到的列表。
我会提出的其他一些建议是:
- 使用更具描述性的名称
- 减少间接使用
- 除了在
self
上设置属性外,不要让 __init__
产生副作用
- 不要违反得墨忒耳的法则所以很难
- 不要做任何你正在做的事情(可能是
*
导入?)导致你在整个过程中洒 #@UndefinedVariable
。
感谢您的及时回答和宝贵的建议,正如我在 post 中所说的那样,我是 python 的新手,但已准备好提高自己。
我分析了你的改动,开始明白原理了,但是有一点没明白:Factory的调用。 _init(self),而且这一行报错,我改成ControllerFactory.init(self),最后删掉。我添加了一些遗漏的初始化并且它有效,非常感谢 :)
这是按照我希望的方式工作的最终代码。
controller.py
class Controller(object):
def __init__(self, port):
# Don't set self.nodes as a class attribute or it is shared across all instances
self.port = port
self.nodes = []
# Don't just use a local for SimpleServer, keep a reference on an attribute. Also, pass the controller instance in.
self.ss = SimpleServer(port, self)
server.py
class MyServerProtocol(Protocol):
def connectionMade(self):
# Get the reference to the Controller instance.
ctrl = self.factory.server.controller
# Use it.
ctrl.nodes.append(self.transport.getPeer())
class ControllerFactory(Factory):
# Set this class attribute so the inherited buildProtocol does the work for us, including setting the factory attribute.
protocol = MyServerProtocol
def __init__(self, server):
# Save a reference to the given server as an attribute on the instance.
self.server = server
#ControllerFactory.__init__(self)
class SimpleServer():
def __init__(self, port, controller):
self.port = port
self.controller = controller
# Pass a reference to the SimpleServer instance to the ControllerFactory
reactor.listenTCP(self.port, ControllerFactory(self))
print 'server listening on %d' %port
reactor.run()
主程序
if __name__ == '__main__':
port = 9123
ctrl = Controller(port)
客户端
class myClientProtocol(Protocol):
def dataReceived(self, data):
print ("data received", data)
class myClientFactory(ClientFactory):
def buildProtocol(self, addr):
print 'Connected.'
return myClientProtocol()
if __name__ == '__main__':
print "CLIENT : connecting to : [ 127.0.0.1 ] on [ 9123 ]\n"
reactor.connectTCP('127.0.0.1',9123, myClientFactory())
reactor.run()
- 我现在将尝试考虑您最后的评论。
我是 python 的新手,对 Twisted 了解更多,如果标题不够清楚,我深表歉意,但我会尽力描述我的问题。
我想在我的应用程序中分离逻辑和网络部分,所以我有 2 个 类 Controller 和 SimpleServer,我在 Controller 中有一个名为 nodes 的变量,我想通过添加客户端 Ip 来更新它每个连接,对于 python 专家来说可能是显而易见的,但我无法理解。请看看我的代码。我评论了我卡住的那一行。
感谢您的帮助
controller.py
class Controller(object):
nodes = []
def __init__(self, port):
ss= SimpleServer(port)
server.py
class MyServerProtocol(Protocol):
def connectionMade(self):
#ctrl.nodeList.append(self.transport.getPeer()) #this is what I want to do
class ControllerFactory(Factory):
def buildProtocol(self, addr):
return MyServerProtocol()
class SimpleServer():
def __init__(self, port):
reactor.listenTCP(port, ControllerFactory()) #@UndefinedVariable
print 'server listening on %d' %port
reactor.run() #@UndefinedVariable
主程序
if __name__ == '__main__':
port = 9123
ctrl = Controller(port)
客户端
class myClientProtocol(Protocol):
def dataReceived(self, data):
print ("data received", data)
class myClientFactory(ClientFactory):
def buildProtocol(self, addr):
print 'Connected.'
return myClientProtocol()
if __name__ == '__main__':
print "CLIENT : connecting to : [ %s ] on [ %s ]\n" %(IP,PORT)
reactor.connectTCP('127.0.0.1',9123, myClientFactory()) #@UndefinedVariable
reactor.run() #@UndefinedVariable
您只需要引用正确的对象。
就像您需要对反应器的引用一样,您导入了 twisted.internet.reactor
以便您可以调用 运行 方法。
controller.py
class Controller(object):
def __init__(self, port):
# Don't set self.nodes as a class attribute or it is shared across all instances
self.nodes = []
# Don't just use a local for SimpleServer, keep a reference on an attribute. Also, pass the controller instance in.
self.ss = SimpleServer(port, self)
server.py
class MyServerProtocol(Protocol):
def connectionMade(self):
# Get the reference to the Controller instance.
ctrl = self.factory.server.controller
# Use it.
ctrl.nodeList.append(self.transport.getPeer())
class ControllerFactory(Factory):
# Set this class attribute so the inherited buildProtocol does the work for us, including setting the factory attribute.
protocol = MyServerProtocol
def __init__(self, server):
# Save a reference to the given server as an attribute on the instance.
self.server = server
Factory.__init__(self)
class SimpleServer():
def __init__(self, port, controller):
self.controller = controller
# Pass a reference to the SimpleServer instance to the ControllerFactory
reactor.listenTCP(port, ControllerFactory(self))
print 'server listening on %d' %port
reactor.run()
主程序
if __name__ == '__main__':
port = 9123
ctrl = Controller(port)
客户端
class myClientProtocol(Protocol):
def dataReceived(self, data):
print ("data received", data)
class myClientFactory(ClientFactory):
def buildProtocol(self, addr):
print 'Connected.'
return myClientProtocol()
if __name__ == '__main__':
print "CLIENT : connecting to : [ %s ] on [ %s ]\n" %(IP,PORT)
reactor.connectTCP('127.0.0.1',9123, myClientFactory()) #@UndefinedVariable
reactor.run() #@UndefinedVariable
我做了我能看到的最小的一组更改来演示解决方案。我还没有测试结果代码。希望您能看到我所做的是引用代码的一部分所具有的对象,并将它们传递给需要它们的代码的其他部分。这通常采用将参数传递给函数(初始化程序、方法等)和设置对象属性(通常是 self 所指的任何内容)的形式。
我没有尝试提高代码的可维护性或更正任何令人担忧的模式。此代码仍然不是理想软件的模型,但它至少应该让您将一个值附加到您希望它附加到的列表。
我会提出的其他一些建议是:
- 使用更具描述性的名称
- 减少间接使用
- 除了在
self
上设置属性外,不要让 - 不要违反得墨忒耳的法则所以很难
- 不要做任何你正在做的事情(可能是
*
导入?)导致你在整个过程中洒#@UndefinedVariable
。
__init__
产生副作用
感谢您的及时回答和宝贵的建议,正如我在 post 中所说的那样,我是 python 的新手,但已准备好提高自己。
我分析了你的改动,开始明白原理了,但是有一点没明白:Factory的调用。 _init(self),而且这一行报错,我改成ControllerFactory.init(self),最后删掉。我添加了一些遗漏的初始化并且它有效,非常感谢 :)
这是按照我希望的方式工作的最终代码。
controller.py
class Controller(object):
def __init__(self, port):
# Don't set self.nodes as a class attribute or it is shared across all instances
self.port = port
self.nodes = []
# Don't just use a local for SimpleServer, keep a reference on an attribute. Also, pass the controller instance in.
self.ss = SimpleServer(port, self)
server.py
class MyServerProtocol(Protocol):
def connectionMade(self):
# Get the reference to the Controller instance.
ctrl = self.factory.server.controller
# Use it.
ctrl.nodes.append(self.transport.getPeer())
class ControllerFactory(Factory):
# Set this class attribute so the inherited buildProtocol does the work for us, including setting the factory attribute.
protocol = MyServerProtocol
def __init__(self, server):
# Save a reference to the given server as an attribute on the instance.
self.server = server
#ControllerFactory.__init__(self)
class SimpleServer():
def __init__(self, port, controller):
self.port = port
self.controller = controller
# Pass a reference to the SimpleServer instance to the ControllerFactory
reactor.listenTCP(self.port, ControllerFactory(self))
print 'server listening on %d' %port
reactor.run()
主程序
if __name__ == '__main__':
port = 9123
ctrl = Controller(port)
客户端
class myClientProtocol(Protocol):
def dataReceived(self, data):
print ("data received", data)
class myClientFactory(ClientFactory):
def buildProtocol(self, addr):
print 'Connected.'
return myClientProtocol()
if __name__ == '__main__':
print "CLIENT : connecting to : [ 127.0.0.1 ] on [ 9123 ]\n"
reactor.connectTCP('127.0.0.1',9123, myClientFactory())
reactor.run()
- 我现在将尝试考虑您最后的评论。