Socket en Python 3


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.

3 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()

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

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