Python est un langage de haut niveau, ce qui fait qu’on a rarement besoin de taper directement dans les interface de couches basses comme les sockets : on utilise des abstractions comme urllib et consort.
Même quand on doit communiquer directement des paquets de données, on préférera utiliser des solutions comme ZeroMQ, bien plus fiables et faciles à mettre en œuvre.
Cela étant dit, pour la culture G, ça ne fait pas de mal d’avoir un petit hello world des sockets en Python.
Client :
import socket # cette fonction n'est pas très performante puisqu'elle # ouvre et ferme la socket pour chaque message, # mais vous voyez le principe. def envoyer_message(ip, port, message): # on ouvre une socket TCP / IP, en IP V4 # la doc contient une liste de constantes avec # les protocoles de base supportés # (http://docs.python.org/2/library/socket.html) # on peut aussi ouvrir des sockets unix, des datagrames... sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((ip, port)) try: # on broadcast le message sock.sendall(message) # et on lit la réponse cash pistache # Tout ça est synchrone, car si on veut # faire de l'asynchrone, l'exemple serait # vachement moins simple response = sock.recv(1024) print "Received: {}".format(response) except Exception as e: print "Impossible de se connecter au serveur: {}".format(e) finally: # toujours fermer sa socket, même si dans notre cas # on a pas besoin de la fermer pour chaque message # On pourrait aussi utiliser le context manager closing() # pour cette tâche sock.close() # petit test qui envoit trois messages if __name__ == "__main__": ip, port = "127.0.0.1", 7777 envoyer_message(ip, port, "Hello World 1") envoyer_message(ip, port, "Hello World 2") envoyer_message(ip, port, "Hello World 3") |
Serveur:
import threading import SocketServer from datetime import datetime # Python vient avec ses serveurs socket tout prêts. # Tout ce qu'il y a faire c'est créer une classe # de handler, c'est à dire l'objet qui va s'occuper # des messages quand ils arrivent. On hérite du # handler de la lib standard, et on redéfinit juste # handle() qui est la méthode qui va être appelée # à chaque message. class RequestHandler(SocketServer.BaseRequestHandler): def handle(self): # on récupère des requêtes, et on répond avec # exactement le même message + un timestamp data = self.request.recv(1024) now = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') response = "{}: {}".format(now, data) self.request.sendall(response) # Pour le serveur, pas grand chose à faire à part le définir # Ici je fais un serveur threadé pour le Lulz car ça # ne sert pas à grand chose pour un client avec 3 messages # synchrones class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass if __name__ == "__main__": # on instancie notre server et on lui passe le gestionnaire de # requêtes server = ThreadedTCPServer(('127.0.0.1', 7777), RequestHandler) ip, port = server.server_address # on start le thread pour le serveur et on le daemonise server_thread = threading.Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() # si on appuie sur "enter", raw_input() s'arrête et le serveur # est stoppé raw_input("Hit enter to stop the server") server.shutdown() |
Je suis d’un niveau pathétique en réseau, alors je vous pond ça vraiment pour le plaisir de partager mes moments bac à sable. Il y a peu de chance que ça vous serve, mais qui sait ?
P.S: je ne suis pas sur mon OS, donc je mettrai les outputs et le code en ligne plus tard.
Dire que je suis en train de faire ça en C en ce moment. J’en pleure encore ! Sinon j’essaierai ça en Python du coup la prochaine fois même si c’est carrément la même chose (presque)…
Piece of cake!
Petites notes:
Pour la création de la socket, socket.socket() peut suffire.
Pour le serveur j’ai ça perso :