IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau/Web Python Discussion :

python, tkinter et les sockets (et les threads)


Sujet :

Réseau/Web Python

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 48
    Points : 33
    Points
    33
    Par défaut python, tkinter et les sockets (et les threads)
    bonjour a tous,
    Je suis en train de galerer a creer une appli client/serveur (un classique me direz vous. sauf que la je dois integrer une interface graphique avec tkinter.

    Mon probleme c'est que le mainloop de tkinter me bloque la reception des messages. En effet j'ai un thread de reception comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class reception_c(th.Thread):
        def __init__(self,conn):
            th.Thread.__init__(self)
            self.connexion = conn
            condition = th.Condition()
    
            while 1:
                    message = self.connexion.recv(255)
                    print message
    
                    if not message:
                        pass
                        print "detection de deconnection du serveur\n"
                        break
    et cest donc la ligne avec le recv qui me bloque car lui me bloque l'ensemble du programme.

    quand je met
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    thread_ecoute=reception_c(self.connexion)
            fenetre.mainloop()
    c'est l'interface graphique qui ne demarre pas et quand j'inverse, l'interface graphique demarremais pas l'ecoute, je n'y comprend rien.

    J'ai recherché du coté de la socket blockante ou bien du cote des files d'attente de thread mais je n'arrive pas a les mettre en place.

    voilou, si quelqu'un voit pourquoi çà bloque

    merci d'avance

  2. #2
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Je suis incapable de répondre mais ce message pour te signaler que tu n'es pas le premier à être victime de recv qui semble poser un problème particulier:

    http://www.developpez.net/forums/d62...urllib-socket/

    http://www.developpez.net/forums/d63...rllib-urlopen/

    Je n'ai pas eu assez de courage jusqu'à présent pour m'attaquer à ce problème pour le comprendre avec mes faibles connaissances de base.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 48
    Points : 33
    Points
    33
    Par défaut
    merci pour ta réponse, il semble en effet que recv pose des problème. Cependant mon probleme est lié surtout a tkinter donc j'oriente surtout mes recherches vers ce module.

    a+

  4. #4
    Membre émérite
    Avatar de DelphiManiac
    Homme Profil pro
    Homme à tout faire
    Inscrit en
    Mars 2002
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Homme à tout faire
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 147
    Points : 2 533
    Points
    2 533
    Par défaut
    Etant curieux de nature et n'ayant pas la réponse, je me suis penché sur la question et il ne me semble pas y avoir de problème, a moins que je n'ai pas bien compris la question.

    Le serveur de test :
    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
    #-*- coding: utf-8 -*- 
     
    # Définition d'un serveur réseau gérant un système de CHAT simplifié.
    # Utilise les threads pour gérer les connexions clientes en parallèle.
     
    HOST = 'localhost'
    PORT = 40000
     
    import socket, sys, threading
     
    class ThreadClient(threading.Thread):
        '''dérivation d'un objet thread pour gérer la connexion avec un client'''
        def __init__(self, conn):
            threading.Thread.__init__(self)
            self.connexion = conn
     
        def run(self):
            # Dialogue avec le client :
            nom = self.getName()        # Chaque thread possède un nom
            while 1:
                msgClient = self.connexion.recv(1024)
                if msgClient.upper() == "FIN" or msgClient =="":
                    break
                message = "%s> %s" % (nom, msgClient)
                print message
                # Faire suivre le message à tous les autres clients :
                for cle in conn_client:
    #                if cle != nom:      # ne pas le renvoyer à l'émetteur
                    conn_client[cle].send(message)
     
            # Fermeture de la connexion :
            self.connexion.close()      # couper la connexion côté serveur
            del conn_client[nom]        # supprimer son entrée dans le dictionnaire
            print u"Client %s déconnecté." % nom
            # Le thread se termine ici    
     
    # Initialisation du serveur - Mise en place du socket :
    mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        mySocket.bind((HOST, PORT))
    except socket.error:
        print u"La liaison du socket à l'adresse choisie a échoué."
        sys.exit()
    print u"Serveur prêt, en attente de requêtes ..."
    mySocket.listen(5)
     
    # Attente et prise en charge des connexions demandées par les clients :
    conn_client = {}                # dictionnaire des connexions clients
    while 1:    
        connexion, adresse = mySocket.accept()
        # Créer un nouvel objet thread pour gérer la connexion :
        th = ThreadClient(connexion)
        th.start()
        # Mémoriser la connexion dans le dictionnaire : 
        it = th.getName()        # identifiant du thread
        conn_client[it] = connexion
        print u"Client %s connecté, adresse IP %s, port %s." %\
               (it, adresse[0], adresse[1])
        # Dialogue avec le client :
        connexion.send("Vous êtes connecté. Envoyez vos messages.")
    Le client de test :
    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
    #!/bin/python
     
    import socket;
    import sys;
    import Tkinter;
     
    #-*- coding: utf-8 -*- 
     
    # Définition d'un client réseau gérant en parallèle l'émission
    # et la réception des messages (utilisation de 2 THREADS).
     
    host = 'localhost'
    port = 40000
     
    import socket, sys, threading
     
    class ThreadReception(threading.Thread):
        """objet thread gérant la réception des messages"""
        def __init__(self, conn):
            threading.Thread.__init__(self)
            self.connexion = conn           # réf. du socket de connexion
     
        def run(self):
            while 1:
                message_recu = self.connexion.recv(1024)
                print "*" + message_recu + "*"
                if message_recu =='' or message_recu.upper() == "FIN":
                    break
            # Le thread <réception> se termine ici.
            # On force la fermeture du thread <émission> :
            print u"Client arrêté. Connexion interrompue."
            self.connexion.close()
     
    class fenetre(threading.Thread):
        def run(self):
            Tkinter.Label(text = "Welcome!").pack();
            Tkinter.Button(text = "Send coucou", command = self.send_many).pack();
            Tkinter.Button(text = "Se déconnecter", command = self.send_FIN).pack();
            Tkinter.mainloop();
     
        def send_many(self):
            many = send_coucou(connexion)
            many.start()
     
        def send_FIN(self):
            connexion.send('FIN')
     
    class send_coucou(threading.Thread):
        def __init__(self, connexion):
            threading.Thread.__init__(self)
            self.connexion = connexion
     
        def run(self):
            for i in xrange(1, 10000):
                self.connexion.send('coucou %s\r\n' % i)
     
    # Programme principal - Établissement de la connexion :
    connexion = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        connexion.connect((host, port))
    except socket.error:
        print u"La connexion a échoué."
        sys.exit()    
    print u"Connexion établie avec le serveur."
    Connected = False;
     
    # Dialogue avec le serveur : on lance deux threads pour gérer
    # indépendamment l'émission et la réception des messages :
    th_R = ThreadReception(connexion)
    th_R.start()
    fen = fenetre()
    fen.start()
    Le serveur ne fais que faire un echo de ce qu'il reçoit. Après avoir lancé le server et le client, je peut cliquer l'envois de coucou les messages passent bien entre les 2 sans qu'aucun des 2 ne soit bloqué.

    Désolé, c'est du copier/coller à l'arrache de différents exemples, sûrement pas très propre. Merci à http://fr.wikibooks.org/wiki/Apprend...un_r%C3%A9seau pour la source du copier/coller
    Si ce message vous a semblé utile, il est possible qu'il soit utile à d'autres personnes. Pensez au . Et n'oubliez pas le le moment venu !

    On n'a pas à choisir si l'on est pour ou contre la décroissance, elle est inéluctable, elle arrivera qu'on le veuille ou non.

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 48
    Points : 33
    Points
    33
    Par défaut
    hallucinant, cela faisait plus d'une semaine que j'essayai pleins de possibilités sans trouver de solutions concluantes...

    Merci beaucoup DelphiManiac, pour cette réponse pertinente, le pire c'est que tes 2 morceaux de codes ne sont pas très différents de ce que j'avais refait, il va falloir que j'y regarde de plus près.

    En tout cas c'est exactement ce qu'il me fallait.

    merci beaucoup, bonne soirée

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 48
    Points : 33
    Points
    33
    Par défaut
    tant que j'y suis, en regardant le programme je vois que les variables d'un même module sont accessibles dans n'importe quelle classe. Je me trompe?

    a+ bonne soirée

  7. #7
    Membre émérite
    Avatar de DelphiManiac
    Homme Profil pro
    Homme à tout faire
    Inscrit en
    Mars 2002
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Homme à tout faire
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 147
    Points : 2 533
    Points
    2 533
    Par défaut
    Oui, les variables ont différentes portées comme dans la plupart des langages. Regarde la documentation, tu trouveras tout les éléments.
    Si ce message vous a semblé utile, il est possible qu'il soit utile à d'autres personnes. Pensez au . Et n'oubliez pas le le moment venu !

    On n'a pas à choisir si l'on est pour ou contre la décroissance, elle est inéluctable, elle arrivera qu'on le veuille ou non.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Les Sockets et les accents
    Par sbranders dans le forum Réseau/Web
    Réponses: 2
    Dernier message: 28/08/2009, 17h51
  2. Les sockets sous les applications console
    Par h4mz4 dans le forum Débuter
    Réponses: 13
    Dernier message: 30/04/2009, 10h33
  3. [WD10] Les sockets et les valeurs nulles
    Par Tems dans le forum WinDev
    Réponses: 1
    Dernier message: 25/08/2008, 10h14
  4. les livre sur les sockets
    Par fullben dans le forum Contribuez
    Réponses: 3
    Dernier message: 25/03/2007, 21h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo