Outils pour utilisateurs

Outils du site


using_perspective_broker

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
using_perspective_broker [2022/11/30 12:28] – [Exemple simple] sergeusing_perspective_broker [2022/12/16 10:42] (Version actuelle) – [Using Perspective Broker] serge
Ligne 1: Ligne 1:
 ======Using Perspective Broker====== ======Using Perspective Broker======
 +{{ :media_01:apkv_20.svg |}}
 +
 +{{ ::labo.svg |}}
 +
 <WRAP center round info centeralign 60%> <WRAP center round info centeralign 60%>
-**Niveau Pro et intergalactique !**+**Niveau Pro et intergalactique !**\\ 
 +Cette API: 
 +  * a entre 15 et 20 ans 
 +  * n'est que vaguement maintenu 
 +  * un exemple au moins ne marche pas 
 +  * le tranfert de datas simples marche 
 +  * le transfert d'objets complexes ne marche pas 
 +  * les exemples ne respectent pas le PEP 8, c'est imbriqué au possible
 </WRAP> </WRAP>
  
 <WRAP center round box 60% > <WRAP center round box 60% >
   * **{{tagpage>perspectivebroker|Toutes les pages Twisted Perspective Broker}}**   * **{{tagpage>perspectivebroker|Toutes les pages Twisted Perspective Broker}}**
-  * **[[perspective_broker|Page précédente]]**+  * **[[perspective_broker|Page précédente]]** Python: Twisted Perspective Broker 
 +  * **[[managing_clients_of_perspectives|Page suivante]]** Managing Clients of Perspectives 
 +  * **[[https://github.com/sergeLabo/PB|Les fichiers sources]]**
 </WRAP> </WRAP>
  
Ligne 13: Ligne 26:
  
 =====Exemple simple===== =====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 ???? m(\\ et en plus gérer les erreurs !+**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 ???? m( et en plus gérer les erreurs !\\
 Tout simplement pour avoir un exemple court, malheureusement comme c'est court, on y comprends rien, pour un Hello World, c'est raté.\\ Tout simplement pour avoir un exemple court, malheureusement comme c'est court, on y comprends rien, pour un Hello World, c'est raté.\\
 Pas grave, nous allons comprendre la suite ! 8-) Pas grave, nous allons comprendre la suite ! 8-)
Ligne 222: Ligne 235:
 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. 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.
  
-=====Page suivante: Twisted Perspective Broker et Kivy===== +=====Exemple 4: Echanges bidirectionnels===== 
-  * **[[twisted_perspective_broker_et_kivy|Twisted Perspective Broker et Kivy]]**+Cet exemple est trop confus, il est le mélange de 2 et 3. Il est une étape intermédiaire avec l'exemple 5. 
 +====Code==== 
 +<file python pb4server.py> 
 +""" 
 +Serveur: Echange bidirectionnel serveur client 
 +""" 
 +from twisted.internet import reactor 
 +from twisted.spread import pb 
 + 
 +class ObjetAccessibleParLeClient(pb.Referenceable): 
 +    """Cette class permet de créer un objet pour en avoir un à partager, 
 +    mais il ne fait rien dans cet exemple 
 +    L'objet accessible par le client est client_accessible 
 +    """ 
 +    pass 
 + 
 +class ObjetPrincipal(pb.Root): 
 +    def __init__(self, client_accessible): 
 +        self.client_accessible = client_accessible 
 +    def remote_getObject(self):  # ancien remote_getTwo 
 +        """Méthode appelée par "getObject" chez le client avec 
 +            self.oneRef.callRemote("getObject").addCallback(self.step2) 
 +        """ 
 +        print(f"Le client a reçu: {self.client_accessible}") 
 +        return self.client_accessible 
 +    def remote_checkObject(self, new_client_accessible):  # ancien remote_checkTwo 
 +        """Méthode appelée par "checkTwo" chez le client 
 +        self.oneRef.callRemote("checkTwo", client_accessible) 
 +        """ 
 +        print(f"Mon client_accessible est: {self.client_accessible}") 
 +        print(f"Le client_accessible est:  {new_client_accessible}") 
 +        if self.client_accessible == new_client_accessible: 
 +            print("Les client_accessible sont les mêmes") 
 +    def remote_takeTwo(self, two): 
 +        """takeTwo""" 
 +        print(f"Le serveur à reçu du client un Two: {two}") 
 +        print("Le serveur demande au client: print(12)") 
 +        two.callRemote("print", 12) 
 + 
 +# un object auquel le client pourra accéder 
 +client_accessible = ObjetAccessibleParLeClient() 
 +# L'objet principal réseau qui tourne 
 +root_obj = ObjetPrincipal(client_accessible) 
 +reactor.listenTCP(8800, pb.PBServerFactory(root_obj)) 
 +reactor.run() 
 +</file> 
 + 
 +<file python pb4client.py> 
 +""" 
 +Client: Echange bidirectionnel serveur client 
 +""" 
 +from twisted.internet import reactor 
 +from twisted.spread import pb 
 + 
 +class Two(pb.Referenceable): 
 +    def remote_print(self, arg): 
 +        print(f"Two.print() appelé par le serveur avec l'argument: {arg}") 
 +        print(arg) 
 + 
 +class Foo: 
 +    """Permet de créer l'objet principal client qui tourne""" 
 +    def __init__(self): 
 +        """self.root_obj_client sera l'objet principal du serveur root_obj""" 
 +        self.root_obj_client = None 
 +    def step1(self, obj): 
 +        self.root_obj_client = obj 
 +        obj_server = self.root_obj_client.callRemote("getObject") 
 +        print(f"Le client a accès à: {obj_server}") 
 +        obj_server.addCallback(self.step2) 
 +    def step2(self, client_accessible): 
 +        print(f"Got object from server: {client_accessible}") 
 +        print(f"Giving it back to server: {self.root_obj_client}") 
 +        self.root_obj_client.callRemote("checkObject", client_accessible) 
 + 
 +def got_obj(obj, two): 
 +    print("J'ai eu l'objet:", obj) 
 +    print(f"Je lui donne le mien {two}") 
 +    obj.callRemote("takeTwo", two) 
 +def main(): 
 +    foo = Foo() 
 +    two = Two() 
 +    factory = pb.PBClientFactory() 
 +    reactor.connectTCP("localhost", 8800, factory) 
 +    factory.getRootObject().addCallback(foo.step1) 
 +    def1 = factory.getRootObject() 
 +    def1.addCallback(got_obj, two)  # hands our 'two' to the callback 
 +    reactor.run() 
 +main() 
 +</file> 
 +=====Exemple 5: Un vrai client/serveur===== 
 +Le serveur tourne.\\ 
 +Dans une boucle, le client récupére des infos sur le serveur, et lui envoie lui aussi des valeurs. 
 + 
 +<file python pb5server.py> 
 + 
 +from time import sleep 
 +from threading import Thread 
 + 
 +from twisted.internet import reactor 
 +from twisted.spread import pb 
 + 
 +class PlayerSimulator(pb.Referenceable): 
 +    """Cette class permet de créer un objet à partager. 
 +    Il simule un player avec: 
 +        - une position de lecture du fichier musical à self.position 
 +        - un track à lire imposé par le client 
 +    L'objet accessible par le client est player 
 +    """ 
 +    def __init__(self): 
 +        self.track = 1 
 +        self.position = 0 
 +        Thread(target=self.thread_update_position).start() 
 + 
 +    def thread_update_position(self): 
 +        n = 0 
 +        while n < 1000: 
 +            n += 1 
 +            self.position += 1 
 +            sleep(1) 
 + 
 +    def remote_newTrack(self, track): 
 +        """New Track imposé par le client""" 
 +        self.track = track 
 +        print(f"Nouveau track demandé par le client {self.track}") 
 + 
 +class ObjetPrincipal(pb.Root): 
 +    def __init__(self, player): 
 +        self.player = player 
 + 
 +    def remote_getPlayerSimulator(self): 
 +        print(f"Le client  demande self.player, je lui retourne") 
 +        return self.player 
 + 
 +    def remote_getPosition(self): 
 +        p = self.player.position 
 +        print(f"Le serveur envoie au client la position {p}") 
 +        return p 
 + 
 +# un object auquel le client pourra accéder 
 +player = PlayerSimulator() 
 + 
 +# L'objet principal réseau qui tourne 
 +root_obj = ObjetPrincipal(player) 
 + 
 +reactor.listenTCP(8800, pb.PBServerFactory(root_obj)) 
 +reactor.run() 
 +</file> 
 + 
 +<file python pb5client.py> 
 +from time import sleep 
 +from threading import Thread 
 + 
 +from twisted.internet import reactor 
 +# Interaction réseau en TCP 
 +from twisted.spread import pb  # Perspetive Broker de Twisted 
 + 
 +class Client: 
 +    """Permet de créer l'objet principal client qui tourne""" 
 + 
 +    def __init__(self): 
 +        """self.root_obj_client sera l'objet principal du serveur root_obj""" 
 +        self.root_obj_client = None 
 +        self.track = 1 
 + 
 +    def on_start(self, obj): 
 +        print(f"on_start: got client_accessible object from server = {obj}") 
 +        self.root_obj_client = obj 
 +        # Appel du Player sur le serveur et ajout du callback 
 +        self.root_obj_client.callRemote("getPlayerSimulator").addCallback(self.run) 
 + 
 +    def run(self, args): 
 +        Thread(target=self.thread_run).start() 
 + 
 +    def thread_run(self): 
 +        n = 0 
 +        while n < 500: 
 +            # Position 
 +            n += 1 
 +            self.root_obj_client.callRemote("getPosition").addCallback(self.print_position) 
 + 
 +            # Changement de track tous les 10 
 +            if n % 10 == 2: 
 +                self.track += 1 
 +                self.root_obj_client.callRemote("getPlayerSimulator").addCallback(self.toto) 
 +            sleep(0.3) 
 + 
 +    def toto(self, args): 
 +        print("args:", args) 
 +        print(f"Envoi du track: {self.track}") 
 +        args.callRemote("newTrack", self.track) 
 + 
 + 
 +    def print_position(self, position): 
 +        print(f"Le client a reçu: {position}") 
 + 
 + 
 +def main(): 
 +    clt = Client() 
 +    factory = pb.PBClientFactory() 
 +    reactor.connectTCP("localhost", 8800, factory) 
 +    factory.getRootObject().addCallback(clt.on_start) 
 +    reactor.run() 
 + 
 +main() 
 +</file> 
 + 
 +=====Transfert d'une image ou d'un json===== 
 +On peut transférer n'import quoi mais il faut toujours convertir ses datas en bytes (octets) avant de les envoyer. Et les décoder à la réception. 
 +<file python > 
 +from time import sleep 
 +from threading import Thread 
 + 
 +import numpy as np 
 +import cv2 
 + 
 +from twisted.internet import reactor 
 +from twisted.spread import pb 
 + 
 +class MyImage: 
 +    def __init__(self): 
 +        self.img = cv2.imread('./covers/Fasokan.jpg') 
 +        img = cv2.resize(self.img, (512, 512)) 
 +        encode_param=[int(cv2.IMWRITE_JPEG_QUALITY), 90] 
 +        result, imgencode = cv2.imencode('.jpg', img, encode_param) 
 +        data = np.array(imgencode) 
 +        print(data.shape) 
 +        self.stringData = data.tobytes() 
 + 
 + 
 +class ObjetPrincipal(pb.Root): 
 +    def __init__(self): 
 +        self.mi = MyImage() 
 +    def remote_image(self): 
 +        print("Le serveur envoie une image") 
 +        return self.mi.stringData 
 + 
 +# L'objet principal réseau qui tourne 
 +root_obj = ObjetPrincipal() 
 + 
 +reactor.listenTCP(8800, pb.PBServerFactory(root_obj)) 
 +reactor.run() 
 +</file> 
 + 
 +<file python > 
 +import numpy as np 
 +import cv2 
 +import base64 
 +from twisted.internet import reactor 
 +from twisted.spread import pb 
 + 
 + 
 +class GetImage(pb.Copyable): 
 +    def get_image(self, stringData): 
 +        image = np.asarray(bytearray(stringData), dtype="uint8") 
 +        image = cv2.imdecode(image, cv2.IMREAD_COLOR) 
 +        print(image.shape) 
 +        cv2.imshow('SERVER', image) 
 +        cv2.waitKey(0) 
 +        cv2.destroyAllWindows() 
 + 
 +class RemoteGetImage(pb.RemoteCopy): 
 +    pass 
 + 
 +pb.setUnjellyableForClass(GetImage, RemoteGetImage) 
 + 
 +class Client: 
 +    """Permet de créer l'objet principal client qui tourne""" 
 +    def __init__(self): 
 +        """self.root_obj_client sera l'objet principal du serveur root_obj""" 
 +        self.root_obj_client = None 
 +        self.gi = GetImage() 
 +    def on_start(self, obj): 
 +        print(f"on_start: got client_accessible object from server = {obj}") 
 +        self.root_obj_client = obj 
 +        # Transfert d'une image 
 +        self.root_obj_client.callRemote("image").addCallback(self.gi.get_image) 
 +         
 +def main(): 
 +    clt = Client() 
 +    factory = pb.PBClientFactory() 
 +    reactor.connectTCP("localhost", 8800, factory) 
 +    factory.getRootObject().addCallback(clt.on_start) 
 +    reactor.run() 
 + 
 +main() 
 +</file> 
 + 
 +=====Page suivante: Passing Complex Types===== 
 +  * **[[pb_copyable_passing_complex_types|PB Copyable Passing Complex Types]]**
  
 {{tag>python sb intergalactique twisted perspectivebroker}} {{tag>python sb intergalactique twisted perspectivebroker}}
using_perspective_broker.1669811296.txt.gz · Dernière modification : de serge