Partage
  • Partager sur Facebook
  • Partager sur Twitter

Messagerie instantanée

Problème de conception ?

    20 octobre 2018 à 22:39:17

    Bonjour,

    Je suis en train de coder une messagerie instantanée pour tester ce que je connais déjà avec les connexions en python. J'ai donc 2 fichiers : le serveur et le client. Sauf que quand je crée l'objet App (qui s'occupe de créer l'interface et qui crée le Thread pour pouvoir gérer parallèlement ce que l'utilisateur fait et la surveillance d'une réception de message), le programme crée mon objet (jusque la tout va bien) sauf que comme je crée le thread dans la méthode __init__() et qu'il rentre dans la "boucle" du Thread directement mon objet n'est pas mis dans la variable destinée. J'ai donc une NameError: name 'app' is not defined quand je veux utiliser ma variable app pour réceptionner un message.

    Je pense que j'ai juste mal confectionné mon code mais je ne trouve pas d'autres moyens pour le moment...

    Les codes sont commentés pour comprendre le fonctionnement.

    serveur.py :

    import socket, select # socket est le module pour créer des connexions
                          # select est celui qui (grâce à la méthode select()) va écouter une liste de sockets
                          # Et qui va renvoyer la liste des clients qui ont un message à récéptionner
    
    connexion_principale = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # création du socket
    connexion_principale.bind(('', 14854))
    connexion_principale.listen(5)
    
    serveur_actif = True
    clients_connectes = []
    while serveur_actif :
        # on regarde si de nouveaux clients ne veulent pas se connecter
        # on attend maximum 50 ms
        connexions_demandees, wlist, xlist = select.select([connexion_principale], [], [], 0.05)
        for connexion in connexions_demandees :
            connexion_avec_client, infos_connexion = connexion.accept()
            clients_connectes.append(connexion_avec_client)
    
        clients_a_lire = []
        try : # on récupère la liste des clients qui ont envoyé un message
            clients_a_lire, wlist, xlist = select.select(clients_connectes, [], [], 0.05)
        except select.error : # exception levée si clients_a_lire est vide
            pass
        else :
            for client in clients_a_lire :
                msg_recu = client.recv(1024) # on réceptionne le message
                msg_recu = msg_recu.decode() # transformation du message de bytes vers str
                print("Reçu : {}".format(msg_recu)) # on l'affiche
                client.send(msg_recu.encode()) # on renvoie le message a tout les clients connectés (même celui qui envoie)
                                               # le message est aussi renvoyé à l'emmeteur mais seulement pour la phase de test du programme
                if msg_recu == "fin" : # si un client envoie "fin", on ferme les connexions
                    serveur_actif = False
                    client.send(b"fin")
    
    print("Fermeture des connexions...")
    for client in clients_connectes :
        client.close()
                
    connexion_principale.close()
    print("Connexions fermées.")
    

    client.py :

    import socket, threading
    import tkinter as tk
    
    class App :
        """Création de l'interface utilisateur."""
        def __init__(self) :
            fen = tk.Tk() # création de l'application
            fen.geometry("440x400")
            fen.title("Messenger du turfu mon gars") # (oui)
            fen.resizable(width = False, height = False)
    
            self.connex = Connexion() # création du thread
            self.connex.start()
    
            # création de l'entry pour entrer le message à envoyer
            self.entry_msgs = tk.Entry(fen, width = 50)
            self.entry_msgs.place(x = 5, y = 383, anchor = "w")
    
            # contient la discussion
            f_conteneur = tk.Frame(fen, width = 310, height = 370, relief = tk.SUNKEN, borderwidth = 2)
            f_conteneur.place(x = 1, y = 1)
            self.conteneurs_msgs = tk.Text(f_conteneur, width = 38, height = 22, state = tk.DISABLED) #state = tk.DISABLED empêche l'utilisateur d'écrire dedans mais empêche aussi l'accès par ligne de code
            self.conteneurs_msgs.pack(side = tk.LEFT)                                                 #démarche à suivre lors d'envoi/récéption de message : modifier le state en tk.NORMAL, ajouter le message, remettre en tk.DISABLED
    
            # envoyer le message
            b_envoi = tk.Button(fen, width = 15, text = "Envoyer", command = self.envoyer_message)
            b_envoi.place(x = 320, y = 370)
    
            # se déconnecter du serveur
            b_deconnexion = tk.Button(fen, width = 15, text = "Se déconnecter", command = self.deconnexion)
            b_deconnexion.place(x = 320, y = 5)
    
            fen.mainloop()
    
        def deconnexion(self) :
            self.connex.deconnecter()
    
        def envoyer_message(self) :
            msg_a_envoyer = self.entry_msgs.get()
            if msg_a_envoyer != "" :
                self.entry_msgs.delete(0, tk.END)
                self.conteneurs_msgs.config(state = tk.NORMAL)
                self.conteneurs_msgs.insert(tk.END, "\nVous : " + msg_a_envoyer)
                self.conteneurs_msgs.config(state = tk.DISABLED)
                self.connex.envoyer_msg(msg_a_envoyer.encode())
    
        def reception_message(self) :
            msg_recu = self.connex.connexion.recv(1024)
            self.conteneurs_msgs.config(state = tk.NORMAL)
            self.conteneurs_msgs.insert(tk.END, msg_recu.decode())
            self.conteneurs_msgs.config(state = tk.DISABLED)
    
    class Connexion(threading.Thread) :
        """Connexion avec le serveur et gestion de la communication hôte-serveur."""
        def __init__(self) :
            threading.Thread.__init__(self)
            self.connexion = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # création du socket
            self.connexion.connect(('localhost', 14854)) # connexion au serveur
    
        def run(self) :
            msg_recu = b"" 
            while msg_recu != b"fin" :
                msg_recu = self.connexion.recv(1024)
                reception_msg()
            print("Serveur déconnecté.")
    
        def deconnecter(self) :
            self.connexion.send(b"fin")
    
        def envoyer_msg(self, msg) :
            self.connexion.send(msg)
    
    def reception_msg() : # méthode intermédiaire car je ne peux pas utiliser la classe App directement dans la classe du Thread
        app.reception_message()
    
    def lancer() :
        global app
        app = App()
    
    lancer()
    

    N'hésitez pas si vous avez des questions.

    Merci !

    • Partager sur Facebook
    • Partager sur Twitter

    Messagerie instantanée

    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
    • Editeur
    • Markdown