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