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 !
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.