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 :

Reseau - Tkinter


Sujet :

Réseau/Web Python

  1. #1
    Membre à l'essai
    Homme Profil pro
    Lyceen
    Inscrit en
    Novembre 2012
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Lyceen
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2012
    Messages : 40
    Points : 18
    Points
    18
    Par défaut Reseau - Tkinter
    Bonsoir,

    Dans le cadre d'un projet scolaire, nous avons essayer, grace au module Socket et Tkinter, de faire deplacer un pion sur map, mais cela en reseau

    En gros, notre serveur affiche notre map et notre pion, pendant que le client s'occupe de le faire bouger.

    Seulement, lorsque le pion a fait 5 cm sur la map client, il n'a meme pas fait 2mm sur la map serveur. Le pion se deplace beaucoup moins vite sur le serveur que sur le client.

    Serveur :

    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
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
     
    ##### SERVEUR TCP - Multi-clients #####
     
    import socket
    import tkinter as tk
    from tkinter import *
    import select
     
    HOTE = 'localhost'   # quelconque
    PORT = 12345
    TAILLE_MAX_PAQUET = 1024
    recu = '' 
    sSrv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sSrv.bind((HOTE, PORT))
    sSrv.listen(5)  # Nbre maxi acceptés "en parallèle"
    print("Le serveur écoute à présent sur le port", PORT)
     
    clients_connectes = []
    serveur_ecoute = True
     
    root2 = Tk()
    fenetre_plateau=Canvas(root2, width="487", height="315")
    photo = PhotoImage(file="mapcouper.gif")
    fenetre_plateau.create_image(243.5, 157.5, image=photo)
    fenetre_plateau.pack()
     
     
     
    carrebleu = [[11,94], [53,94], [11,207], [53,207]]
    carrebleu2 = [[438,92], [478,92], [438,206], [478,206]]
    x = 240
    y = 145
    r = 8
    dx = 0
    dy = 0
    couleur="red"
     
     
    def move(event):
        x = fenetre_plateau.canvasx(event.x)
        y = fenetre_plateau.canvasy(event.y)
        #if (carrebleu2[0][0] < event.x < carrebleu2[1][0] and carrebleu2[0][1] < event.y < carrebleu2[2][1]) or (carrebleu[0][0] < event.x < carrebleu[1][0] and carrebleu[0][1] < event.y < carrebleu[2][1]):
     
     
    def cercle():
        return fenetre_plateau.create_oval(210, 210, 230, 230, fill=couleur,tag = "pion")
     
    def up (event:None):
        global dx
        global dy
        global up
        up=True
        dx = 0
        dy = -1
     
    def down (event:None):
        global dx
        global dy
        global down
        down=True
        dx = 0
        dy = 1
     
    def left (event:None):
        global dx
        global dy
        global left
        left=True
        dx = -1
        dy = 0
     
    def right (event:None):
        global dx
        global dy
        global right
        right=True
        dx = 1
        dy = 0
     
     
    cercle()
     
    root2.bind('<1>', move)
    root2.bind('<Up>', up)
    root2.bind('<Down>', down)
    root2.bind('<Left>', left)
    root2.bind('<Right>', right)
     
    while serveur_ecoute:    # Boucle d'écoute du serveur
        # (1) On vérifie si des nouveaux clients demandent à se connecter
        #  => on écoute le serveur, maxi pendant 0.05 sec.
        connexions_demandees, wlist, xlist = select.select([sSrv],
                                                           [], [], 0.05)
        # en_ecoute, en_ecriture, en_except., pour select.select
        for connexion in connexions_demandees:
            sCli, infos_connexion = connexion.accept()
            # On ajoute le socket connecté à la liste des clients connectés
            clients_connectes.append(sCli)
     
        # (2) Maintenant, on écoute la liste des clients *connectés*
        liste_sCli_a_lire = []
        try:        # sinon, exception levée si la liste des clients est vide
            liste_sCli_a_lire, wlist, xlist = select.select(clients_connectes,
                                                            [], [], 0.05)
        except select.error:
            pass    # Ne rien faire s'il n'y en a pas
        else:
            # On parcourt la liste des clients à lire
            for sCli in liste_sCli_a_lire:
                msg_recu = sCli.recv(TAILLE_MAX_PAQUET) # octets, donc 
                recu = str(msg_recu, encoding="utf-8")  #  à encoder...
                print("'", recu, "' reçu de",       # message,
                      sCli.getpeername()[0],        #  IP et
                      "/", sCli.getpeername()[1])   #  port de l'envoyeur            
                ### Facultatif : accusé de réception #######################
                sCli.send(bytes("'"+recu+"' bien reçu !", encoding="utf-8"))
                ############################################################
        if recu == 'UP':
            dx = 0
            dy = -1
     
        if recu == 'DOWN':
            dx = 0
            dy = 1
     
        if recu == 'LEFT':
            dx = -1
            dy = 0
     
        if recu == 'RIGHT':
            dx = 1
            dy = 0
     
     
        recu=''
     
        fenetre_plateau.move("pion", dx,dy)
        fenetre_plateau.update()
        fenetre_plateau.after(10)
     
     
     
     
     
     
     
     
    print("Fermeture des connexions au serveur")
    for sCli in clients_connectes:
        sCli.close()
    sSrv.close()
    Client :
    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
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
     
    ##### CLIENT TCP #####
     
    import socket
    import tkinter as tk
     
    HOTE = 'localhost' 
    PORT = 12345 
    TAILLE_MAX_PAQUET = 1024
    up = False
    down = False
    left = False
    right = False
    msg_a_envoyer = ''
     
     
    sCli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sCli.connect((HOTE, PORT)) 
    print("Connexion établie avec le serveur sur le port", PORT)
    #############################################
     
    from tkinter import *
     
    root2 = Tk()
    fenetre_plateau=Canvas(root2, width="487", height="315")
    photo = PhotoImage(file="mapcouper.gif")
    fenetre_plateau.create_image(243.5, 157.5, image=photo)
    fenetre_plateau.pack()
     
     
     
    carrebleu = [[11,94], [53,94], [11,207], [53,207]]
    carrebleu2 = [[438,92], [478,92], [438,206], [478,206]]
    x = 240
    y = 145
    r = 8
    dx = 0
    dy = 0
    couleur="red"
     
     
    def move(event):
        x = fenetre_plateau.canvasx(event.x)
        y = fenetre_plateau.canvasy(event.y)
        #if (carrebleu2[0][0] < event.x < carrebleu2[1][0] and carrebleu2[0][1] < event.y < carrebleu2[2][1]) or (carrebleu[0][0] < event.x < carrebleu[1][0] and carrebleu[0][1] < event.y < carrebleu[2][1]):
     
     
    def cercle():
        return fenetre_plateau.create_oval(210, 210, 230, 230, fill=couleur,tag = "pion")
     
    def up (event:None):
        global dx
        global dy
        global up
        up=True
        dx = 0
        dy = -1
     
    def down (event:None):
        global dx
        global dy
        global down
        down=True
        dx = 0
        dy = 1
     
    def left (event:None):
        global dx
        global dy
        global left
        left=True
        dx = -1
        dy = 0
     
    def right (event:None):
        global dx
        global dy
        global right
        right=True
        dx = 1
        dy = 0
     
     
    cercle()
     
    root2.bind('<1>', move)
    root2.bind('<Up>', up)
    root2.bind('<Down>', down)
    root2.bind('<Left>', left)
    root2.bind('<Right>', right)
     
     
     
     
     
    ###################################################
     
    while 1:
        fenetre_plateau.move("pion", dx,dy)
        fenetre_plateau.update()
        fenetre_plateau.after(10)
        # Saisie du message
     
        if up:
            msg_a_envoyer = 'UP'  
        elif down:
            msg_a_envoyer = 'DOWN'
        elif left:
            msg_a_envoyer = 'LEFT'
        elif right:
            msg_a_envoyer = 'RIGHT'
        else:
            fenetre_plateau.update()
     
        # Envoi du message
        if msg_a_envoyer == 'UP' or  msg_a_envoyer == 'DOWN' or msg_a_envoyer == 'LEFT' or msg_a_envoyer == 'RIGHT':
            envoi = bytes(msg_a_envoyer, encoding="utf-8")
            sCli.send(envoi)
     
     
        # Reception de l'accusé, si le serveur en envoie un
            msg_recu = sCli.recv(TAILLE_MAX_PAQUET) # octets, donc 
            recu = str(msg_recu, encoding="utf-8")  #  à encoder...
            print(recu)
            up = False
            down = False
            left = False
            right = False
            msg_a_envoyer = ''
     
        #########################################################
    fen.mainloop()
    J'aimerais savoir d'ou vient cette "latence" sur le serveur.

    Autre chose, je commence dans le reseau, et meme dans la programmation, auriez vous des conseils pour organiser notre code, car j'ai comme l'impression qu'on a coder ca tres mal.

    Bonne soiree

  2. #2
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Vous comprenez bien que si c'est lent c'est que le code est occupé à autre chose, ici principalement dans la partie réseau.
    Pour plus de 'réactivité' vous devez séparer GUI et réseau et cela passe (entre autre) par un thread.
    Le souci c'est que sous Tkinter vous ne pouvez/devez pas toucher aux éléments graphique à partir d'un thread. Une solution est de passer par le module queue:
    Un exemple rapide sans trop toucher a votre partie réseau.
    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
    import socket
    from tkinter import *
    import select
    import queue
    import threading
     
     
    class Serveur(threading.Thread):
        def __init__(self, queue, HOTE='localhost', PORT=12345):
            threading.Thread.__init__(self)
            self.queue = queue
            self.taille_max_paquet = 1024
            self.sSrv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sSrv.bind((HOTE, PORT))
            self.sSrv.listen(5)
            print("Le serveur écoute à présent sur le port", PORT)
            self.clients_connectes = []
            self._stopevent = threading.Event()
        def run(self):
            while not self._stopevent.isSet():
                connexions_demandees, wlist, xlist = select.select([self.sSrv], [], [], 0.05)
                for connexion in connexions_demandees:
                    sCli, infos_connexion = connexion.accept()
                    self.clients_connectes.append(sCli)
                liste_sCli_a_lire = []
                try:
                    liste_sCli_a_lire, wlist, xlist = select.select(self.clients_connectes, [], [], 0.05)
                except (select.error, ValueError):
                    pass
                for sCli in liste_sCli_a_lire:
                    msg_recu = sCli.recv(self.taille_max_paquet) 
                    recu = str(msg_recu, encoding="utf-8")
                    cli = sCli.getpeername()
                    print("'%s' reçu de %s/%s" % (recu, cli[0], cli[1]))
                    sCli.send(bytes("'"+recu+"' bien reçu !", encoding="utf-8"))
                    self.queue.put(recu)
            print("Fin du thread")
            print("Fermeture des connexions au serveur")
            for sCli in self.clients_connectes:
                sCli.close()
            self.sSrv.close()
        def stop(self):
            self._stopevent.set()
     
     
    def update_gui():
        global tomove
        try:
            recu = Eventqueue.get_nowait()
            if recu:
                tomove = recu
        except queue.Empty:
            pass
        if tomove:
            dx, dy = movedic[tomove]
            fenetre_plateau.move("pion", dx, dy)
            fenetre_plateau.update_idletasks()
        root2.after(10, update_gui)
     
     
    def OnQuit():
        s.stop()
        root2.destroy()
     
     
    if __name__ == "__main__":
        Eventqueue = queue.Queue()
        tomove = None
        couleur="red"
        movedic = {'UP':(0, -1), 'DOWN':(0, 1), 'LEFT':(-1, 0), 'RIGHT':(1, 0)}
     
        root2 = Tk()
        fenetre_plateau = Canvas(root2, width="487", height="315")
        # photo = PhotoImage(file="mapcouper.gif")
        # fenetre_plateau.create_image(243.5, 157.5, image=photo)
        fenetre_plateau.pack()
        fenetre_plateau.create_oval(210, 210, 230, 230, fill=couleur, tag="pion")
        s = Serveur(Eventqueue)
        s.start()
        update_gui()
        root2.bind('<Up>', lambda e: Eventqueue.put('UP'))
        root2.bind('<Down>', lambda e: Eventqueue.put('DOWN'))
        root2.bind('<Left>', lambda e: Eventqueue.put('LEFT'))
        root2.bind('<Right>', lambda e: Eventqueue.put('RIGHT'))
        root2.protocol("WM_DELETE_WINDOW", OnQuit)
        root2.mainloop()
        s.stop()
    (J'ai essayer de garder le plus possible de votre code. Donc exemple a corriger)

    @+
    Merci d'utiliser le forum pour les questions techniques.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Lyceen
    Inscrit en
    Novembre 2012
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Lyceen
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2012
    Messages : 40
    Points : 18
    Points
    18
    Par défaut
    Merci, je vais regarder tout ca.

    Une autre chose, je n'arrive pas a comprendre pourquoi lorsque je lance mon client, le pion du serv part vers le haut sans meme appui de la touche Up (J'avais deja ca avant)

    Autre chose, le pion va certe, beaucoup plus vite, mais il ne va toujours pas aussi vite que celui du client, il n'y aura pas moyen de les mettres a vitesse egale ?

  4. #4
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Vous n'avez pas donner du code fonctionnel pour le moment (def up (event:None): ) : Pouvez vous donner le code que vous utilisez ? Cela vas aider pour la suite.
    Sinon pour votre déplacement c'est que votre variable doit sans doute être à 'UP' dans le code que vous utilisez : A voir avec du code fonctionnel pour vous.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  5. #5
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Petite modification de votre client par rapport au serveur : A vous de trouver pourquoi 'UP' n'est pas envoyé dans ce cas
    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
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
     
    ##### CLIENT TCP #####
     
    import socket
    import tkinter as tk
     
    HOTE = 'localhost' 
    PORT = 12345 
    TAILLE_MAX_PAQUET = 100
    up = False
    down = False
    left = False
    right = False
    msg_a_envoyer = ''
     
     
    sCli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sCli.connect((HOTE, PORT)) 
    print("Connexion établie avec le serveur sur le port", PORT)
    #############################################
     
    from tkinter import *
     
    root2 = Tk()
    fenetre_plateau=Canvas(root2, width="487", height="315")
    #photo = PhotoImage(file="mapcouper.gif")
    #fenetre_plateau.create_image(243.5, 157.5, image=photo)
    fenetre_plateau.pack()
     
     
     
    carrebleu = [[11,94], [53,94], [11,207], [53,207]]
    carrebleu2 = [[438,92], [478,92], [438,206], [478,206]]
    x = 240
    y = 145
    r = 8
    dx = 0
    dy = 0
    couleur="red"
    msg_a_envoyer = None
     
     
    def move(event):
        x = fenetre_plateau.canvasx(event.x)
        y = fenetre_plateau.canvasy(event.y)
        #if (carrebleu2[0][0] < event.x < carrebleu2[1][0] and carrebleu2[0][1] < event.y < carrebleu2[2][1]) or (carrebleu[0][0] < event.x < carrebleu[1][0] and carrebleu[0][1] < event.y < carrebleu[2][1]):
     
     
    def cercle():
        return fenetre_plateau.create_oval(210, 210, 230, 230, fill=couleur,tag = "pion")
     
    def up (event=None):
        global dx
        global dy
        global msg_a_envoyer
        msg_a_envoyer = 'UP' 
        dx = 0
        dy = -1
     
    def down (event=None):
        global dx
        global dy
        global msg_a_envoyer
        msg_a_envoyer = 'DOWN'
        dx = 0
        dy = 1
     
    def left (event=None):
        global dx
        global dy
        global msg_a_envoyer
        msg_a_envoyer = 'LEFT'
        dx = -1
        dy = 0
     
    def right (event=None):
        global dx
        global dy
        global msg_a_envoyer
        msg_a_envoyer = 'RIGHT'
        dx = 1
        dy = 0
     
     
    cercle()
     
    root2.bind('<1>', move)
    root2.bind('<Up>', up)
    root2.bind('<Down>', down)
    root2.bind('<Left>', left)
    root2.bind('<Right>', right)
     
     
     
     
     
    ###################################################
     
    while 1:
        fenetre_plateau.move("pion", dx,dy)
        fenetre_plateau.update()
        fenetre_plateau.after(10)
        # Saisie du message
     
     
        # Envoi du message
        if msg_a_envoyer in ('UP', 'DOWN', 'LEFT', 'RIGHT'):
            envoi = bytes(msg_a_envoyer, encoding="utf-8")
            sCli.send(envoi)
            msg_recu = sCli.recv(TAILLE_MAX_PAQUET) # octets, donc 
            recu = str(msg_recu, encoding="utf-8")  #  à encoder...
            print(recu)
            msg_a_envoyer = ''
     
        #########################################################
    fen.mainloop()
    Edit : Vous remarquerez aussi les ralentissement du GUI du client si vous laissez appuyer une touche par rapport au serveur. D’où l’intérêt de séparer réseau et GUI.
    Merci d'utiliser le forum pour les questions techniques.

  6. #6
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Attention aux noms des objets : def up(event=None): / up = False etc...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    >>> up = False
    >>> def up():
    ...     pass
    ... 
    >>> if up:
    ...     print('ok')
    ... 
    ok
    Merci d'utiliser le forum pour les questions techniques.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Lyceen
    Inscrit en
    Novembre 2012
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Lyceen
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2012
    Messages : 40
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Petite modification de votre client par rapport au serveur : A vous de trouver pourquoi 'UP' n'est pas envoyé dans ce cas
    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
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
     
    ##### CLIENT TCP #####
     
    import socket
    import tkinter as tk
     
    HOTE = 'localhost' 
    PORT = 12345 
    TAILLE_MAX_PAQUET = 100
    up = False
    down = False
    left = False
    right = False
    msg_a_envoyer = ''
     
     
    sCli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sCli.connect((HOTE, PORT)) 
    print("Connexion établie avec le serveur sur le port", PORT)
    #############################################
     
    from tkinter import *
     
    root2 = Tk()
    fenetre_plateau=Canvas(root2, width="487", height="315")
    #photo = PhotoImage(file="mapcouper.gif")
    #fenetre_plateau.create_image(243.5, 157.5, image=photo)
    fenetre_plateau.pack()
     
     
     
    carrebleu = [[11,94], [53,94], [11,207], [53,207]]
    carrebleu2 = [[438,92], [478,92], [438,206], [478,206]]
    x = 240
    y = 145
    r = 8
    dx = 0
    dy = 0
    couleur="red"
    msg_a_envoyer = None
     
     
    def move(event):
        x = fenetre_plateau.canvasx(event.x)
        y = fenetre_plateau.canvasy(event.y)
        #if (carrebleu2[0][0] < event.x < carrebleu2[1][0] and carrebleu2[0][1] < event.y < carrebleu2[2][1]) or (carrebleu[0][0] < event.x < carrebleu[1][0] and carrebleu[0][1] < event.y < carrebleu[2][1]):
     
     
    def cercle():
        return fenetre_plateau.create_oval(210, 210, 230, 230, fill=couleur,tag = "pion")
     
    def up (event=None):
        global dx
        global dy
        global msg_a_envoyer
        msg_a_envoyer = 'UP' 
        dx = 0
        dy = -1
     
    def down (event=None):
        global dx
        global dy
        global msg_a_envoyer
        msg_a_envoyer = 'DOWN'
        dx = 0
        dy = 1
     
    def left (event=None):
        global dx
        global dy
        global msg_a_envoyer
        msg_a_envoyer = 'LEFT'
        dx = -1
        dy = 0
     
    def right (event=None):
        global dx
        global dy
        global msg_a_envoyer
        msg_a_envoyer = 'RIGHT'
        dx = 1
        dy = 0
     
     
    cercle()
     
    root2.bind('<1>', move)
    root2.bind('<Up>', up)
    root2.bind('<Down>', down)
    root2.bind('<Left>', left)
    root2.bind('<Right>', right)
     
     
     
     
     
    ###################################################
     
    while 1:
        fenetre_plateau.move("pion", dx,dy)
        fenetre_plateau.update()
        fenetre_plateau.after(10)
        # Saisie du message
     
     
        # Envoi du message
        if msg_a_envoyer in ('UP', 'DOWN', 'LEFT', 'RIGHT'):
            envoi = bytes(msg_a_envoyer, encoding="utf-8")
            sCli.send(envoi)
            msg_recu = sCli.recv(TAILLE_MAX_PAQUET) # octets, donc 
            recu = str(msg_recu, encoding="utf-8")  #  à encoder...
            print(recu)
            msg_a_envoyer = ''
     
        #########################################################
    fen.mainloop()
    Edit : Vous remarquerez aussi les ralentissement du GUI du client si vous laissez appuyer une touche par rapport au serveur. D’où l’intérêt de séparer réseau et GUI.
    Si l'on separe le reseau de l'interface Graphique, cela resoudrait completement les problemes de decalage du mouvement ?

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 239
    Points : 36 692
    Points
    36 692
    Par défaut
    Citation Envoyé par bromy Voir le message
    Si l'on separe le reseau de l'interface Graphique, cela resoudrait completement les problemes de decalage du mouvement ?
    Dans le code initial, vous faites un appel à .move toutes les 10ms.
    Côté serveur, çà attend 50ms la réception d'une nouvelle connextion puis encore 50ms secondes la réception d'un message.
    Enfin, çà poste un .move à faire dans 10ms: si côté serveur les appels à .move se font toutes les 100ms, çà se déplace 10 fois moins vite.

    Le gros soucis est que le serveur "attend" un changement de direction. Comme le déplacement sur les clients et le serveur sont "asynchrones", je ne vois pas comment ce qui sera affiché côté "serveur" pourra être "fidèle" à ce qui se passe côté clients.

    Il serait plus "simple" de faire que les clients expédient la position "courante" à intervalles réguliers et que le "serveur" fasse des ".move" à partir de là.

    Séparer réseau et interface graphique permet de construire et tester chaque partie (réseau, graphique) indépendamment l'une de l'autre. Il n'est pas indispensable de mettre la partie réseau dans un thread séparé. Mais comme vous ne savez pas trop où vous voulez aller, le coût est raisonnable.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonsoir wiztricks,

    Citation Envoyé par wiztricks Voir le message
    Il serait plus "simple" de faire que les clients expédient la position "courante" à intervalles réguliers et que le "serveur" fasse des ".move" à partir de là.
    N'est il pas plus logique que cela soit le serveur qui donne la position ? Le 'client' n'est là que pour modifier la 'trajectoire' dans le code d'origine (voir les binds du serveur + les send).
    Cela impliquerais qu'il n'y est de move sur le client 'que' par rapport aux coordonnées reçues et affiner le timing réseau / que les temps d'attentes soit égaux des deux cotés.

    Citation Envoyé par wiztricks Voir le message
    Séparer réseau et interface graphique permet de construire et tester chaque partie (réseau, graphique) indépendamment l'une de l'autre. Il n'est pas indispensable de mettre la partie réseau dans un thread séparé. Mais comme vous ne savez pas trop où vous voulez aller, le coût est raisonnable.
    Est ce a dire que vous préconisez de gérer la partie de code réseau avec le mainloop ?
    Cela implique que les temps d'attentes soit égaux des deux cotés.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 239
    Points : 36 692
    Points
    36 692
    Par défaut
    Salut PauseKawa,

    Citation Envoyé par PauseKawa Voir le message
    N'est il pas plus logique que cela soit le serveur qui donne la position ? Le 'client' n'est là que pour modifier la 'trajectoire' dans le code d'origine (voir les binds du serveur + les send).
    C'est pas une question de logique mais de cas d'utilisation: que fait le serveur? que feront les clients?
    Pour l'instant, pas grand chose pour décider.
    J'ai l'impression que le serveur aura pour fonction de "broadcaster" les changements de position des "clients" - un peu comme un "chat" -.
    A côté de ces "broadcasts", il faudrait réaliser: ajout d'un jouer, une gestion des jeux, des commandes de type request/response.

    Si c'est le cas, le choix de la techno. réseau utilisée sera sans doute à revoir.
    Ceci dit, c'est un projet "scolaire".

    On peut espérer que les enseignants l'encadrent un peu pour limiter les fonctionnalités plutôt que de laisser les élèves partir dans tous les sens et en sortir "frustrés": faire un jeu réseau avec un display graphique sans plan ni bibliothèques qui machent un peu le boulot et "cachent" les difficultés me semble "irresponsable".

    Est ce a dire que vous préconisez de gérer la partie de code réseau avec le mainloop ? Cela implique que les temps d'attentes soit égaux des deux cotés
    Je ne le préconise pas: c'est trop "sportif" pour des débutants.
    Mais "techniquement", pousser la partie réseau dans un thread n'est pas indispensable.
    Avec les threads, réseau et interface graphique sont deux activités "asynchrones". Le asynchrone est nécessaire pour gérer les attentes et les timeouts côté réseau en gardant "fluide" l'interface graphique.

    Ceci dit une écriture réseau n'attend pas la lecture côté récepteur pour redonner la main à l'appelant du .send(sd, buffer). Et il n'est pas utile de "bloquer" forever lorsqu'il n'y a rien à lire: les messages non lus "attendront"
    d'être lus, dans la pile côté récepteur.

    L'interface graphique pouvant lire et écrire "sans délais" pas besoin d'avoir des activités "asynchrones". Coder cela demande une certaine expérience des "features" de la programmation avec les "sockets".
    Les threads "simplifient" grandement cela et "forcent" à séparer/tester indépendamment: ce qui est "mieux" même si on peut "techniquement" s'en passer.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    Membre à l'essai
    Homme Profil pro
    Lyceen
    Inscrit en
    Novembre 2012
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Lyceen
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2012
    Messages : 40
    Points : 18
    Points
    18
    Par défaut
    Je suis un peu perdu x) Il y a pas mal de vocabulaire que je ne connais pas.

    Autre chose, le projet n'est pas encadree par les profs, et c'est ca qui est mal fait.

    En gros, eux ils font leurs cours d'informatique et science du numerique, et nous on fait notre projet avec les connaissances apprises.

    Concretement, vous nous conseillez de nous y prendre comment au final ?

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 239
    Points : 36 692
    Points
    36 692
    Par défaut
    Citation Envoyé par bromy Voir le message
    Concretement, vous nous conseillez de nous y prendre comment au final ?
    Commencez par décrire en français les fonctionnalités de votre jeu sur une ou deux pages. Puis essayez de voir comment les réaliser (toujours en français).

    nous on fait notre projet avec les connaissances apprises.
    Si vous n'avez pas appris la programmation d'un GUI, réseau, threads,... çà ne sera pas "facile". Le problème est que vous devrez rendre votre copie un jour ou l'autre et que le temps que vous aller pouvoir passer à coder est compté.

    Une fois que vous aurez décrit le quoi/comment (en français) il sera peut être intéressant d'aller en discuter avec vos profs pour voir s'ils peuvent vous aider un peu.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. [VB6] [Réseau] Connexion et partage de données
    Par tomnie dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 21/10/2002, 19h12
  2. Connecter un lecteur reseau
    Par manusweb dans le forum C++Builder
    Réponses: 4
    Dernier message: 03/09/2002, 13h07
  3. Creer un reseau local via l adsl
    Par loki dans le forum Développement
    Réponses: 11
    Dernier message: 12/08/2002, 01h14
  4. reseau de neuronnes
    Par mumu2001 dans le forum Méthodes prédictives
    Réponses: 3
    Dernier message: 25/07/2002, 10h33

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