Python: notion de client / serveur ********************************** Il existe de nombreux modes de communication en mode client / serveur. Bon nombre de ces modes possèdent déjà dans python des modules prêt à l'emploi +--------+------------------+-------+--------------------------+ |Protocol|Common function |Port No|Python module | +--------+------------------+-------+--------------------------+ |HTTP |Web pages |80 |httplib, urllib, xmlrpclib| |NNTP |Usenet news |119 |nntplib | |FTP |File transfers |20 |ftplib, urllib | |SMTP |Sending email |25 |smtplib | |POP3 |Fetching email |110 |poplib | |IMAP4 |Fetching email |143 |imaplib | |Telnet |Command lines |23 |telnetlib | |Gopher |Document transfers|70 |gopherlib, urllib | +--------+------------------+-------+--------------------------+ Mais il est parfois utile de repartir de 0 ou presque pour générer une application client / serveur Exemple simple ============== On va utiliser pour cela la notion de socket le programme pour le server (fichier server.py) .. code-block:: python #!/usr/bin/python # This is server.py file import socket # Import socket module s = socket.socket() # Create a socket object host = socket.gethostname() # Get local machine name port = 12345 # Reserve a port for your service. s.bind((host, port)) # Bind to the port s.listen(5) # Now wait for client connection. while True: c, addr = s.accept() # Establish connection with client. print 'Got connection from', addr c.send('Thank you for connecting') c.close() # Close the connection le programme pour le client (fichier client.py) .. code-block:: python #!/usr/bin/python # This is client.py file import socket # Import socket module s = socket.socket() # Create a socket object host = socket.gethostname() # Get local machine name port = 12345 # Reserve a port for your service. s.connect((host, port)) print s.recv(1024) s.close # Close the socket when done quand on lance chaque programme on a coté serveur :: C:\Users\f.aoustin.PROPLAST\Desktop>python server.py Got connection from ('194.0.4.251', 3150) coté client :: C:\Users\f.aoustin.PROPLAST\Desktop>python client.py Thank you for connecting On note que le seveur à nue boucle infinie pour toujours être à l'écoute d'un client Il est possible de modifier le code pour qu'on puisse envoyer plus d'une commande le programme pour le server (fichier server.py) .. code-block:: python import socket Sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) Host = '127.0.0.1' # l'ip locale de l'ordinateur Port = 234 # choix d'un port # on bind notre socket : Sock.bind((Host,Port)) # On est a l'ecoute d'une seule et unique connexion : Sock.listen(1) # Le script se stoppe ici jusqu'a ce qu'il y ait connexion : client, adresse = Sock.accept() # accepte les connexions de l'exterieur print "L'adresse",adresse,"vient de se connecter au serveur !" while 1: RequeteDuClient = client.recv(255) # on recoit 255 caracteres grand max if not RequeteDuClient: # si on ne recoit plus rien break # on break la boucle (sinon les bips vont se repeter) print RequeteDuClient,"\a" # affiche les donnees envoyees, suivi d'un bip sonore le programme pour le client (fichier client.py) .. code-block:: python import socket # on importe le module Sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # on cree notre socket # definition des informations : Host = '127.0.0.1' Port = 234 # on se connecte sur le serveur avec les informations ci-dessus # assurez-vous d'avoir mis en marche le serveur ! Sock.connect((Host,Port)) # On est connecte, on fait une boucle infinie d'inputs pour l'envoi des messages : while 1: msg = raw_input('>> ') # on rentre des donnees Sock.send(msg) # on envoie ces donnees # regardez ce qui se passe du cote serveur. Un client server en XML RPC =========================== XML-RPC est un protocole RPC (Remote procedure call), une spécification simple et un ensemble de codes qui permettent à des processus s'exécutant dans des environnements différents de faire des appels de méthodes à travers un réseau. XML-RPC permet d'appeler une fonction sur un serveur distant à partir de n'importe quel système (Windows, Mac OS X, GNU/Linux) et avec n'importe quel langage de programmation. Le serveur est lui même sur n'importe quel système et est programmé dans n'importe quel langage. Cela permet de fournir un Service web utilisable par tout le monde sans restriction de système ou de langage. Les processus d'invocation à distance utilisent le protocole HTTP pour le transfert des données et la norme XML pour la structuration des données. XML-RPC est conçu pour permettre à des structures de données complexes d'être transmises, exécutées et renvoyées très facilement. XML-RPC est l'ancêtre de SOAP. le programme pour le server (fichier server.py) un exemple concret .. code-block:: python import SocketServer from SimpleXMLRPCServer import SimpleXMLRPCServer,SimpleXMLRPCRequestHandler import sys import os # Threaded mix-in class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer) : pass # Example class to be published class TestObject: def sysReq(self,data): return os.system(data) def pow(self, x, y): return pow(x, y) def add(self, x, y) : return x + y def divide(self, x, y): return float(x) / float(y) # Instantiate and bind to localhost:8080 server = AsyncXMLRPCServer(('localhost', 8080), SimpleXMLRPCRequestHandler) # Register example object instance server.register_instance(TestObject()) server.register_introspection_functions() # run! server.serve_forever() le programme pour le client (fichier client.py) .. code-block:: python import xmlrpclib import sys s = xmlrpclib.ServerProxy('http://localhost:8080') print s.pow(2,3) # Returns 2**3 = 8 print s.add(2,3) # Returns 5 print s.div(5,2) # Returns 5//2 = 2 # Print list of available methods print s.system.listMethods() print s.sysReq(sys.argv[1]) .. note:: le module xmlrpc a changé de nom entre python2 et python3 pour avoir un code compatible il faut utiliser ce genre de code .. code-block:: python try: # Python 2 from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler from SimpleXMLRPCServer import SimpleXMLRPCServer except ImportError: # Python 3 from xmlrpc.server import SimpleXMLRPCRequestHandler from xmlrpc.server import SimpleXMLRPCServer try: # Python 2 from xmlrpclib import ServerProxy, ProtocolError except ImportError: # Python 3 from xmlrpc.client import ServerProxy, ProtocolError