Ceci est une ancienne révision du document !
Table des matières
Using Perspective Broker
Niveau Pro et intergalactique !
Traduction Google de Using Perspective Broker améliorée par un humain ayant fait intergalactique en 1ère langue !
Exemple simple
Passez votre chemin, cela revient à expliquer la factorisation à un élève de 5ème, en lui parlant de nombres complexes et de cosinus hyperbolique: pourquoi utiliser des “lambda” qui ne sont pas pythoniques ????
Exemple 1
La méthode remote_three() du serveur est appelée par le client avec
obj2.callRemote("three", 12)
De manière générale, sur le client, on peut appeler remote_toto(un_argument) avec
truc.callRemote("toto", un_argument)
Cela appelle la méthode à distance et cela transfert un_argument du client au serveur!
La taille maxi de l'argument est décrit ici: 640 * 1024 bytes ou entier de +ou- 2448
Cette façon de procéder est une des 3 façons possibles(saveurs).
- pb1server.py
from twisted.spread import pb class Two(pb.Referenceable): def remote_three(self, arg): """Appelé par le callback three sur le client obj2.callRemote("three", 12) """ print("Two.three was given", arg) class One(pb.Root): def remote_getTwo(self): """Appelé par le callback getTwo sur le client def2 = obj1.callRemote("getTwo") """ two = Two() print("returning a Two called", two) return two from twisted.internet import reactor reactor.listenTCP(8800, pb.PBServerFactory(One())) reactor.run()
- pb1client.py
from twisted.spread import pb from twisted.internet import reactor def main(): factory = pb.PBClientFactory() reactor.connectTCP("localhost", 8800, factory) def1 = factory.getRootObject() def1.addCallbacks(got_obj1) reactor.run() def got_obj1(obj1): print("got first object:", obj1) print("asking it to getTwo") def2 = obj1.callRemote("getTwo") def2.addCallbacks(got_obj2) def got_obj2(obj2): print("got second object:", obj2) print("telling it to do three(12)") obj2.callRemote("three", 12) main()
Explications
Exemple 2: Accès aux objets du serveur depuis le client
Si votre serveur donne une référence(à un objet) à un client, puis que ce client renvoie la référence au serveur, le serveur se retrouvera avec le même objet qu'il a donné à l'origine. La couche de sérialisation surveille le retour des identifiants de référence et les transforme en objets réels. Vous devez rester conscient de l'emplacement de l'objet : s'il est de votre côté, vous effectuez des appels de méthode réels. Si c'est de l'autre côté, vous faites des .callRemote()(appel à distance).
Cela crée 2 univers identiques. Les objets sont les mêmes mais pas au mêmes endroits: un sur le serveur, un sur le client.
Code
- pb2server.py
from twisted.internet import reactor from twisted.spread import pb class Two(pb.Referenceable): def remote_print(self, arg): print("class Two dans serveur: two.print was given", arg) class One(pb.Root): def __init__(self, two): # pb.Root.__init__(self) # pb.Root doesn't implement __init__ self.two = two def remote_getTwo(self): """Méthode appelée par getTwo chez le client avec self.oneRef.callRemote("getTwo").addCallback(self.step2)""" print("One.getTwo(), returning my two called", self.two) return self.two def remote_checkTwo(self, new_two): """Méthode appelée par checkTwo chez le client self.oneRef.callRemote("checkTwo", two)""" print("appelé par quoi ?") print("One.checkTwo(): comparing my two", self.two) print("One.checkTwo(): against your two", new_two) if self.two == new_two: print("One.checkTwo(): our twos are the same") two = Two() root_obj = One(two) reactor.listenTCP(8800, pb.PBServerFactory(root_obj)) reactor.run()
- pb2client.py
from twisted.internet import reactor from twisted.spread import pb def main(): foo = Foo() factory = pb.PBClientFactory() reactor.connectTCP("localhost", 8800, factory) factory.getRootObject().addCallback(foo.step1) reactor.run() class Foo: """Garder les globals autour commence à devenir moche, nous utilisons donc une classe simple à la place. Au lieu d'accrocher une fonction à la suivante, nous accrochons une méthode à la suivante.""" def __init__(self): self.oneRef = None def step1(self, obj): print("got one object:", obj) self.oneRef = obj print("asking it to getTwo") self.oneRef.callRemote("getTwo").addCallback(self.step2) def step2(self, two): print("got two object:", two) print("giving it back to one") print("one is", self.oneRef) self.oneRef.callRemote("checkTwo", two) main()
Explications
Le serveur donne une Two()instance au client, qui renvoie ensuite la référence au serveur. Le serveur compare les “deux” donnés avec les “deux” reçus et montre qu'ils sont identiques, et que les deux sont des objets réels au lieu de références distantes.
Quelques autres techniques sont démontrées dans pb2client.py. La première est que les rappels sont ajoutés avec .addCallback au lieu de .addCallbacks. Comme vous pouvez le voir dans la documentation Deferred.addCallback , il s'agit d'un formulaire simplifié qui n'ajoute qu'un rappel de réussite. L'autre est que pour garder une trace de l'état d'un rappel à l'autre (la référence distante à l'objet principal One()), nous créons une classe simple, stockons la référence dans une instance de celle-ci et pointons les rappels vers une séquence de méthodes liées. C'est un moyen pratique d'encapsuler une machine d'état. Chaque réponse lance la méthode suivante, et toutes les données qui doivent être transportées d'un état à l'autre peuvent simplement être enregistrées en tant qu'attribut de l'objet.
N'oubliez pas que le client peut vous rendre toute référence à distance que vous lui avez donnée. Ne basez pas votre serveur de transactions boursières de plusieurs milliards de dollars sur l'idée que vous faites confiance au client pour vous donner la bonne référence. Le modèle de sécurité inhérent à PB signifie qu'ils ne peuvent vous rendre qu'une référence que vous leur avez donnée pour la connexion en cours (pas celle que vous avez donnée à quelqu'un d'autre à la place, ni celle que vous leur avez donnée la dernière fois avant la fin de la session TCP, ni celui que vous n'avez pas encore donné au client), mais tout comme avec les URL et les cookies HTTP, la référence particulière qu'ils vous donnent est entièrement sous leur contrôle.
Exemple 3: Accès aux objets coté client
Tout ce qui est référençable peut être transmis sur le fil, dans les deux sens . Le “client” peut donner une référence au “serveur”, puis le serveur peut utiliser .callRemote() pour invoquer des méthodes côté client. Cela brouille la distinction entre « client » et « serveur » : la seule vraie différence est qui initie la connexion TCP d'origine ; après c'est tout symétrique.
Code
- pb3server.py
from twisted.internet import reactor from twisted.spread import pb class One(pb.Root): def remote_takeTwo(self, two): """takeTwo""" print("received a Two called", two) print("telling it to print(12)") two.callRemote("print", 12) reactor.listenTCP(8800, pb.PBServerFactory(One())) reactor.run()
- pb3client.py
from twisted.internet import reactor from twisted.spread import pb class Two(pb.Referenceable): def remote_print(self, arg): print("Two.print() called with", arg) def main(): two = Two() factory = pb.PBClientFactory() reactor.connectTCP("localhost", 8800, factory) def1 = factory.getRootObject() def1.addCallback(got_obj, two) # hands our 'two' to the callback reactor.run() def got_obj(obj, two): print("got One:", obj) print("giving it our two") obj.callRemote("takeTwo", two) main()
Explications
Dans cet exemple, le client donne une référence à son propre objet au serveur. Le serveur appelle ensuite une méthode distante sur l'objet côté client.