Socket en Python


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.

5 thoughts on “Socket en Python

  • Blef

    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)…

  • JeromeJ

    Piece of cake!

    Petites notes:

    Pour la création de la socket, socket.socket() peut suffire.

    Pour le serveur j’ai ça perso :

    import socketserver
     
    class Client(socketserver.BaseRequestHandler):
        def setup(self):
            pass # Initialisez comme bon vous semble
     
        def handle(self):
            pass # Boucle qui gère la réception des messages
     
        def finish(self):
            pass # Est appelé lorsque la socket se ferme
     
    server = socketserver.ThreadingTCPServer(('', 12345), Client) 
    server.daemon_threads = True # Il tuera les daemons à l'arrêt du serveur au lieu d'attendre leur mort (= déconnection de tous les clients)
    server.serve_forever()
  • pat

    bonjour

    j’ai parcouru autant d’exemples que j’ai pu trouvés en php et en python et je n’ai pas trouvé d’exemples simples qui fonctionnent avec lesquels on puisse établir un dialogue entre serveur et client

    envoi de message serveur –> client

    envoi de message client –> serveur

    si quelqu’un a une adresse, je suis preneur

    merci pour vos réponses

    ps : j’ai aussi essayé des scripts de chat ou d’irc mais pas possible de les faire tourner sur ma debian

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.