Sie haben das grundlegende Design gut etabliert. Es ist ein grundlegender "Mann in der Mitte" Ansatz. Es gibt viele Möglichkeiten, es zu implementieren, aber das sollte Ihnen den Einstieg:
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()
Die Kernlogik, die die Daten von dem Server zu Akteuren werden proxied empfangen erlaubt ist proxy_factory.actors = set()
und actor_factory.actors = proxy_factory.actors
. Die meisten "list-like" Container sind aus Mangel an besseren Wörtern "global" und dieses Beispiel gibt Kontext in die Factory-Objekte jeder Verbindung. Wenn ein Akteur eine Verbindung mit dem Server herstellt, wird ein Actor
Protokoll an die set
angehängt, und wenn Daten empfangen werden, erhält jedes Protokoll in set
die Daten. Siehe die entsprechenden dataReceived()
Methoden jedes Protokollobjekts, wie das funktioniert.
Das obige Beispiel verwendet keine globalen Variablen, aber das heißt nicht, dass Sie sie nicht verwenden könnten. Sehen Sie, wie weit Sie mit dieser Methode der Weitergabe von Variablen, die Kontext in andere Objekte geben können. Außerdem wurden bestimmte Situationen nicht explizit behandelt, z. B. das Zwischenspeichern empfangener Daten für den Fall, dass der Server oder die Akteure noch nicht verbunden waren. Hoffentlich gibt es hier genug Informationen für Sie, um die beste Vorgehensweise für Ihre Bedürfnisse zu bestimmen. Es gibt einige Möglichkeiten, die Syntax zu straffen, um sie auch kürzer zu machen.
Als eine Randnotiz. Eine Alternative zu globalen Variablen ist picobox. Es ist eine Dependency-Injector-Bibliothek, aber ich habe festgestellt, dass sie die meisten meiner Anforderungen erfüllt, wenn ich Parameter von externen Quellen benötige.
Fragen Sie, wie Sie dies ohne globale Variablen tun? Die Frage nach einem "besseren Weg" ist extrem offen. –