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 NNTP FTP SMTP POP3 IMAP4 Telnet Gopher | Web pages Usenet news File transfers Sending email Fetching email Fetching email Command lines Document transfers | 80 119 20 25 110 143 23 70 | httplib, urllib, xmlrpclib nntplib ftplib, urllib smtplib poplib imaplib telnetlib 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)
#!/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)
#!/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)
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)
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
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)
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
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