Python Twisted 向代理发送事件信号的最佳方式
Python Twisted best way to signal events to a proxy
我将托管一项服务,该服务的行为有点像我作为客户的代理。
所以我希望我的 ProxyService(twisted.protocol 服务器)能够接收大量参与者(客户端)。在服务器端,我需要一个全局连接(所有客户端只需要 1 个连接)到一个 ExistingService(代码不是我写的,我是一个客户端到它)。
- 当 ExistingService 说一些有趣的事情时,我需要将它广播给所有演员。
- 当演员对我的 ProxyService 说些什么时,我需要检查它是否适合我。如果是,我需要通知 ExistingService。
我想我知道如何使用全局变量解决这个问题,但只是想知道是否有更好的方法来推送消息。
您的基本设计已经很好地建立起来了。
这是一种基本的 "man in the middle" 方法。
有很多方法可以实现它,但这应该可以帮助您入门:
from twisted.internet import endpoints, protocol, reactor
class ProxyClient(protocol.Protocol):
def connectionMade(self):
print('[x] proxy connection made to server')
self.factory.proxy_proto = self
def connectionLost(self, reason):
print('[ ] proxy connection to server lost: {0}'.format(reason))
self.factory.proxy_proto = None
def dataReceived(self, data):
print('==> received {0} from server'.format(data))
print('<== transmitting data to all actors')
for actor in self.factory.actors:
actor.transport.write(data)
class Actor(protocol.Protocol):
def connectionMade(self):
print('[x] actor connection established')
self.factory.actors.add(self)
def connectionLost(self, reason):
print('[ ] actor disconnected: {0}'.format(reason))
self.factory.actors.remove(self)
def dataReceived(self, data):
print('==> received {0} from actor'.format(data))
proxy_connection = self.factory.proxy_factory.proxy_proto
if proxy_connection is not None:
print('<== transmitting data to server through the proxy')
proxy_connection.transport.write(data)
else:
print('[ ] proxy connection to server has not been established')
def setup_servers():
PROXY_HOST = '127.0.0.1'
PROXY_PORT = 9000
proxy_factory = protocol.ClientFactory()
proxy_factory.protocol = ProxyClient
proxy_factory.proxy_proto = None
proxy_factory.actors = set()
proxy_client = endpoints.TCP4ClientEndpoint(reactor, port=PROXY_PORT, host=PROXY_HOST)
proxy_client.connect(proxy_factory)
ACTOR_HOST = '127.0.0.1'
ACTOR_PORT = 8000
actor_factory = protocol.Factory()
actor_factory.protocol = Actor
actor_factory.proxy_factory = proxy_factory
actor_factory.actors = proxy_factory.actors
actor_server = endpoints.TCP4ServerEndpoint(reactor, port=ACTOR_PORT, interface=ACTOR_HOST)
actor_server.listen(actor_factory)
def main():
setup_servers()
reactor.run()
main()
允许将从服务器接收的数据代理给参与者的核心逻辑是proxy_factory.actors = set()
和actor_factory.actors = proxy_factory.actors
。
大多数 "list-like" 容器,由于缺乏更好的词,是 "global" 并且这个例子为每个连接的工厂对象提供了上下文。
当 actor 连接到服务器时,Actor
协议附加到 set
并且当接收到数据时,set
中的每个协议都将获取数据。
请参阅每个协议对象各自的 dataReceived()
方法,了解其工作原理。
上面的例子根本没有使用全局变量,但这并不是说你不能使用它们。
看看使用这种将上下文传递给其他对象的变量的方法你能走多远。
此外,某些情况未明确处理,例如在服务器或参与者尚未连接的情况下缓存接收到的数据。
希望这里有足够的信息供您根据您的需要确定最佳行动方案。
还有一些空间可以简化语法以使其更短。
作为旁注。全局变量的替代方法是 picobox。它是一个依赖注入器库,但我发现当我需要来自外部源的参数时,它可以满足我的大部分需求。
我将托管一项服务,该服务的行为有点像我作为客户的代理。
所以我希望我的 ProxyService(twisted.protocol 服务器)能够接收大量参与者(客户端)。在服务器端,我需要一个全局连接(所有客户端只需要 1 个连接)到一个 ExistingService(代码不是我写的,我是一个客户端到它)。
- 当 ExistingService 说一些有趣的事情时,我需要将它广播给所有演员。
- 当演员对我的 ProxyService 说些什么时,我需要检查它是否适合我。如果是,我需要通知 ExistingService。
我想我知道如何使用全局变量解决这个问题,但只是想知道是否有更好的方法来推送消息。
您的基本设计已经很好地建立起来了。 这是一种基本的 "man in the middle" 方法。 有很多方法可以实现它,但这应该可以帮助您入门:
from twisted.internet import endpoints, protocol, reactor
class ProxyClient(protocol.Protocol):
def connectionMade(self):
print('[x] proxy connection made to server')
self.factory.proxy_proto = self
def connectionLost(self, reason):
print('[ ] proxy connection to server lost: {0}'.format(reason))
self.factory.proxy_proto = None
def dataReceived(self, data):
print('==> received {0} from server'.format(data))
print('<== transmitting data to all actors')
for actor in self.factory.actors:
actor.transport.write(data)
class Actor(protocol.Protocol):
def connectionMade(self):
print('[x] actor connection established')
self.factory.actors.add(self)
def connectionLost(self, reason):
print('[ ] actor disconnected: {0}'.format(reason))
self.factory.actors.remove(self)
def dataReceived(self, data):
print('==> received {0} from actor'.format(data))
proxy_connection = self.factory.proxy_factory.proxy_proto
if proxy_connection is not None:
print('<== transmitting data to server through the proxy')
proxy_connection.transport.write(data)
else:
print('[ ] proxy connection to server has not been established')
def setup_servers():
PROXY_HOST = '127.0.0.1'
PROXY_PORT = 9000
proxy_factory = protocol.ClientFactory()
proxy_factory.protocol = ProxyClient
proxy_factory.proxy_proto = None
proxy_factory.actors = set()
proxy_client = endpoints.TCP4ClientEndpoint(reactor, port=PROXY_PORT, host=PROXY_HOST)
proxy_client.connect(proxy_factory)
ACTOR_HOST = '127.0.0.1'
ACTOR_PORT = 8000
actor_factory = protocol.Factory()
actor_factory.protocol = Actor
actor_factory.proxy_factory = proxy_factory
actor_factory.actors = proxy_factory.actors
actor_server = endpoints.TCP4ServerEndpoint(reactor, port=ACTOR_PORT, interface=ACTOR_HOST)
actor_server.listen(actor_factory)
def main():
setup_servers()
reactor.run()
main()
允许将从服务器接收的数据代理给参与者的核心逻辑是proxy_factory.actors = set()
和actor_factory.actors = proxy_factory.actors
。
大多数 "list-like" 容器,由于缺乏更好的词,是 "global" 并且这个例子为每个连接的工厂对象提供了上下文。
当 actor 连接到服务器时,Actor
协议附加到 set
并且当接收到数据时,set
中的每个协议都将获取数据。
请参阅每个协议对象各自的 dataReceived()
方法,了解其工作原理。
上面的例子根本没有使用全局变量,但这并不是说你不能使用它们。 看看使用这种将上下文传递给其他对象的变量的方法你能走多远。 此外,某些情况未明确处理,例如在服务器或参与者尚未连接的情况下缓存接收到的数据。 希望这里有足够的信息供您根据您的需要确定最佳行动方案。 还有一些空间可以简化语法以使其更短。
作为旁注。全局变量的替代方法是 picobox。它是一个依赖注入器库,但我发现当我需要来自外部源的参数时,它可以满足我的大部分需求。