Bonjour à tous,

Je m'attaque à PyQt en créant/bidouillant un Chat en réseaux.

Je suis actuellement confronté à un bug pour le moins étrange (à moins que ce soit une feature).

Je ne reçois que la première lettre des envois du serveur... alors qu'à un moment donné cela fonctionnait très bien (enfin plus ou moins).
En gros je devrais recevoir : shaoling : coucou, mais je reçois seulement s.
Pourtant le serveur reçoit bien tout ce qu'il faut (ça affiche en console ce que ça devrait renvoyer).
Donc soit il y a un problème lors de l'envoie server -> client, soit il y a un problème sur l'affichage du client...

Vous pouvez télécharger les sources ci-dessous, mais je vous affiche quand même mon code.
http://www.megaupload.com/?d=QWMW22EH

Fichier server.py :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import sys, socket
import threading
 
class Server:
    def __init__(self, address):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.bind(address)
        self.socket.listen(5)
 
        self.clients = []
 
    def wait_for_clients(self):
        while True:
            client, address = self.socket.accept()
            self.clients.append(client)
            t = ListeningThread(self.clients, client)
            t.start()
 
 
class ListeningThread(threading.Thread):
    def __init__(self, clients, client):
        threading.Thread.__init__(self)
        self.clients = clients
        self.client = client
 
    def run(self):
        name = self.client.recv(1024)
        address = self.client.getsockname()
        message = "<b>%s</b> %s connected" % (name, address)
        self.send_to_all(message)
        while True:
            message = self.client.recv(1024)
            if message == "":
                self.clients.remove(self.client)
                message = "<b>" + name + "</b> disconnected"
                self.send_to_all(message)
                break
            message = "<b>" + name + "</b>: " + message
            self.send_to_all(message)
 
    def send_to_all(self, message):
        print message
        for client in self.clients:
            client.send(message)
 
if len(sys.argv) != 3:
    print """Usage: python server.py ip port
example: python server.py localhost 54321"""
    sys.exit()
 
address = sys.argv[1], int(sys.argv[2])
server = Server(address)
server.wait_for_clients()
Fichier connexion.py : # Fenetre de connexion
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# -*- coding: utf-8 -*-
 
import sys
import socket
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from chat import FenetreChat
 
 
PORT=54321
 
class FenetreConnexion(QDialog):
    """Fenêtre de connexion de l'application iTchat"""
 
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setFixedSize(300,150)
        self.setWindowTitle('Connexion')
        size_ecran = QDesktopWidget().screenGeometry()
        size_fenetre = self.geometry()
 
        # Serveur
        self.layout_serveur = QHBoxLayout()
        self.serveur = QLabel('Serveur : ')
        self.input_serveur = QLineEdit()
        self.layout_serveur.addWidget(self.serveur)
        self.layout_serveur.addWidget(self.input_serveur)
 
        # Pseudo
        self.layout_pseudo = QHBoxLayout()
        self.pseudo = QLabel('Pseudo : ')
        self.input_pseudo = QLineEdit()
        self.layout_pseudo.addWidget(self.pseudo)
        self.layout_pseudo.addWidget(self.input_pseudo)
 
        # Boutons OK et Quitter
        self.layout_boutons = QHBoxLayout()
        self.bouton_ok = QPushButton('Se Connecter')
        self.bouton_quitter = QPushButton('Quitter')
        QDialog.connect(self.bouton_ok, SIGNAL("clicked()"), self.check_infos)
        QDialog.connect(self.bouton_quitter, SIGNAL("clicked()"), quit)
        self.bouton_quitter.clicked.connect(quit)
        self.layout_boutons.addWidget(self.bouton_ok)
        self.layout_boutons.addWidget(self.bouton_quitter)
 
        # Layout principal
        self.layout_principal = QVBoxLayout()
        self.layout_principal.addLayout(self.layout_serveur)
        self.layout_principal.addLayout(self.layout_pseudo)
        self.layout_principal.addLayout(self.layout_boutons)
 
        self.setLayout(self.layout_principal)
 
        # on centre la fenetre
        self.move((size_ecran.width()-size_fenetre.width())/2, (size_ecran.height()-size_fenetre.height())/2)
 
    def check_infos(self):
        """Vérifie les informations entrées dans le formulaire de connexion"""
        self.serveur = self.input_serveur.text().trimmed()
        self.pseudo = self.input_pseudo.text().trimmed()
 
        if self.serveur == '' or self.pseudo == '':
            msg = QMessageBox.warning(self, u"Erreur !", u"Veuillez indiquer l'adresse du serveur ainsi que votre pseudo !")
        elif not self.pseudo.contains(QRegExp(r"^\w+$")):
            msg = QMessageBox.warning(self, u"Erreur !", u"Votre pseudo ne doit contenir que des lettres, chiffres et underscores !")
        else:
            self.connexion(self.serveur, self.pseudo)
 
 
    def connexion(self, serveur, pseudo):
        """Etablit la connexion au serveur"""
 
        # dès que tout est OK, on tente la connexion
        self.sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.sock.connect((serveur, PORT))
        except socket.gaierror:
            QMessageBox.critical(self, u"Erreur !", u"Impossible de se connecter au serveur indiqué !")
            return
 
        print "Connexion au serveur > %s : %s avec le pseudo %s" % (serveur, PORT, pseudo)
        self.sock.send(pseudo)
 
        # Affichage de la fenetre principale
        tchat = FenetreChat(self.sock, self)
        tchat.show()
        # On cache la fenetre de connexion
        self.hide()
 
 
 
 
 
if __name__ == "__main__":
    app = QApplication(sys.argv)
    connexion = FenetreConnexion()
    connexion.show()
    sys.exit(app.exec_())
Fichier chat.py : # Fenetre principale du tchat
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# -*- coding: utf-8 -*-
 
from PyQt4.QtCore import *
from PyQt4.QtGui import *
 
 
 
class FenetreChat(QDialog):
    """Fenêtre principale de l'application iTchat"""
 
    def __init__(self, sock, parent=None):
        QDialog.__init__(self, parent)
        self.sock = sock
        self.parent = parent
        self.resize(600,500)
        self.setMinimumWidth(600) # Largeur minimale
        self.setMinimumHeight(500) # Hauteur minimale
        self.setWindowTitle('iTchat')
        size_ecran = QDesktopWidget().screenGeometry()
        size_fenetre = self.geometry()
 
        # on centre la fenetre
        self.move((size_ecran.width()-size_fenetre.width())/2, (size_ecran.height()-size_fenetre.height())/2)
 
        # Layouts du haut, du bas, et principal comprenant haut et bas
        self.layout_haut = QHBoxLayout()
        self.layout_bas = QHBoxLayout()
        self.layout_principal = QVBoxLayout()
 
        # Contenu du layout_haut
        self.tchat = QTextEdit()
        self.tchat.setReadOnly(True)
        self.tchat.append(u"<font color='red'><b>Connecté.</b></font>")
        self.connectes = QListWidget()
        self.connectes.setMaximumWidth(200) # Largeur maximale
        self.layout_haut.addWidget(self.tchat)
        self.layout_haut.addWidget(self.connectes)
 
        # Contenu du layout_bas
        self.input_texte = QLineEdit()
        self.bouton_envoyer = QPushButton('Envoyer')
        self.bouton_envoyer.setDefault(True)
        self.layout_bas.addWidget(self.input_texte)
        self.layout_bas.addWidget(self.bouton_envoyer)
 
        # Contenu du layout_principal
        self.layout_principal.addLayout(self.layout_haut)
        self.layout_principal.addLayout(self.layout_bas)
        self.setLayout(self.layout_principal)
 
 
        QWidget.connect(self.bouton_envoyer, SIGNAL("clicked()"), self.envoyer)
        self.listening_thread = ListeningThread(self, self.sock)
        self.connect(self.listening_thread, SIGNAL("message_recu"), self.recevoir)
 
        self.listening_thread.start()
 
 
    def envoyer(self):
        message = self.input_texte.text().trimmed()
        if message != '':
            self.sock.send(message)
            self.input_texte.setText('')
 
    def recevoir(self, message):
        self.tchat.append(message)
 
    def closeEvent(self, event):
        self.listening_thread.terminate()
        self.sock.close()
        QWidget.deleteLater(self)
        self.parent.close()
        event.accept()
 
 
class ListeningThread(QThread):
    def __init__(self, parent, socket):
        QThread.__init__(self, parent)
        self.parent = parent
        self.socket = socket
        self.running = True
 
    def run(self):
        while self.running:
            message = self.socket.recv(1024)
            self.emit(SIGNAL("message_recu"), message)
            QApplication.processEvents()
Et enfin fichier client.py :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
import sys
#from PyQt4.QtCore import *
from PyQt4.QtGui import *
from connexion import FenetreConnexion
 
app = QApplication(sys.argv)
fenetre = FenetreConnexion()
fenetre.show()
app.exit(app.exec_())
Pour lancer le serveur :
$ python server.py localhost 54321
Pour lancer le client :
$ python client.py
Il faut entrer localhost dans la case client, et le pseudo que vous souhaitez.

Si quelqu'un pouvait m'indiquer d'où provient l'erreur je lui en serait reconnaissant, mes recherches n'ont rien données...

Merci d'avance !