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

PyQt Python Discussion :

Récupérer des données dans un QTableView depuis une base de données par le réseau


Sujet :

PyQt Python

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Août 2009
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 195
    Points : 156
    Points
    156
    Par défaut Récupérer des données dans un QTableView depuis une base de données par le réseau
    Bonjour

    Dans notre boite, notre erp développé maison (a long time ago) est basé sur "base de données" memfile (accès séquentiel) (crée par société française memsoft).
    Je suis en partie là pour maintenir/ évoluer le truc... (Ca serait moi on changerait car on est très fragile, produit obsolète,.. mais là n'est pas le sujet)

    On se peut pas accéder du tout par un autre langage avec odbc ou autre à notre base de données hormis le langage du memsoft (le membasic)
    Une application serveur memfile gère les accès fichier.
    Grâce à wireshark et de l'analyse de paquet, je suis parvenu à dialoguer par socket (ouverture fichier, lire, suivant, précdent, mise a jour, écriture..).
    Heureusement il n y avait pas de cryptage!

    Maintenant que la communication avec le monde extérieure est possible, on souhaite mettre en place un site web qui a accès à notre super base de données.
    Le but est de permettre à nos clients de consulter en real time leur stock/ commandes / embarquement/ ...

    Dans un premier temps, j'avais retranscrit mon module python en php qui communiquait sur notre programme serveur memfile..
    Ça fonctionne moyennement.. un des problème : les sessions restent actives sur notre serveur memfile (et nous sommes limités à 255 sessions moins nos 150 sessions environ en interne )

    J'avais idée (peut être mauvaise) de réaliser une 'passerelle' python qui :
    - gère les accés (pouvant limiter à 10 sessions par exemple)
    - déconnecter les sessions inactives depuis 10 minutes
    - controler dans la mesure du possible les données recues du web pour pas faire planter notre serveur memfile
    - autoriser les connexions sur telle plage horaire
    - ...

    D'où mon intervention sur le sujet, j'ai fait une ébauche de script pour faire la passerelle, ça semble fonctionner pour les échanges..

    Dans le code ci dessous, je complète un tableau avec mes threads clients connectés..
    Dans chacun de ces threads client, j'ai des infos basiques(heure inscription, nbre requête, login,..)
    Je veux faire apparaître ces infos dans une vue (QTableView).. c'est là que je bloque dans la réflexion.
    En passant par un model (QAbstractTableModel) qui se base sur mon tableau?
    Et à coup de SIGNAL pour rafraichir ma table?
    Mais où? par les threadClients? par un timer?

    Soyez indulgent, ce n'est qu'une ébauche

    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
     
    # -*- coding: utf-8 -*- 
    import socket
    import sys
    import binascii
    import os
    import threading
    from PyQt4 import QtGui
    from PyQt4 import QtCore
     
    WEB_PORT = 5002
     
     
    MEMFILE_PORT = 5001
    MEMFILE_HOST = '192.168.0.205'
     
    class modelClient(QtCore.QAbstractTableModel):
      def __init__(self, parent=None):
    		super(modelClient,self).__init__(parent)
     
     
    class ThreadClient(QtCore.QThread):
      def __init__(self, conn):
        super(ThreadClient, self).__init__()
        self.conn_web = conn    # Connexion web
        self.login = self.conn_web.recv(1024)      # Login
        self.nb_req_envoi = 0   # Nbre requete vers web
        self.nb_req_recu  = 1   # Nbre requete du web
        self.heure_connex = QtCore.QTime.currentTime() # Heure d'inscription
        self.connex_Memfile()
     
      def connex_Memfile(self): # Connexion serveur Memfile
        stream_c = '500060000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000530000'
        try:
          self.conn_mf.connect((MEMFILE_HOST, MEMFILE_PORT))
          self.conn_mf.send(binascii.unhexlify(stream_c))
          rec = self.conn_mf.recv(1024)
          session = rec[16:17]
          self.session = binascii.hexlify(session)
          self.conn_web.send(rec)
          self.nb_req_envoi +=1
        except :
          print 'erreur de connexion'
     
      def run(self):
        while True:
          msgWeb = self.conn_web.recv(5120)
          self.nb_req_recu +=1
          self.conn_mf.send(msgWeb)         # envoi au serveur memfile
          rep = self.conn_mf.recv(5120)     # reception du serveur memfile
          self.conn_web.send(rep)           # envoi reponse au web
          self.nb_req_envoi +=1
     
     
     
    class ThreadServeur(QtCore.QThread):
      def __init__(self, parent):
        super(ThreadServeur, self).__init__()
        self.parent  = parent
        try:
          self.parent.webSocket.bind(('localhost',WEB_PORT))
          self.parent.webSocket.listen(5)
        except socket.error:
          print "erreur liaison socket"
     
      def run(self): # socket connexion web
        while True:
          connexion, adresse = self.parent.webSocket.accept()
          th = ThreadClient(connexion)
          self.parent.clients.append(th)
          th.run()
     
     
    class WidgServeur(QtGui.QMainWindow):
      def __init__(self, parent=None):
        super(WidgServeur, self).__init__(parent)
        self.setup()
        self.clients = []
     
      def setup(self):
        self.statusBar().showMessage(u'')
        self.setActions()
        self.setMenu()
        self.widg = QtGui.QWidget() #------------------  Widget central
        self.widg.setLayout(QtGui.QHBoxLayout())   
        self.wTools = QtGui.QWidget() #----------------  Barre outils 
        self.wTools.setLayout(QtGui.QVBoxLayout())
        self.wTools.setFixedWidth(100)
        self.butStart = QtGui.QPushButton('Start!')
        self.butStart.clicked.connect(self.startServeur)
        self.butOptions = QtGui.QPushButton('Options')
        self.butQuit = QtGui.QPushButton('Quitter')
     
        self.wTools.layout().addWidget(self.butStart)
        self.wTools.layout().addSpacing(40)
        self.wTools.layout().addWidget(self.butOptions)
        self.wTools.layout().addStretch()
        self.wTools.layout().addWidget(self.butQuit)
        self.table = QtGui.QTableView() #------------  Table 
        #self.table.setMinimumWidth(500)
        #self.table.setMinimumHeight(300)
        #self.table.setColumnCount(3)
        #self.table.setHorizontalHeaderLabels(["Session","Connexion","Derniere activite"])
        #self.table.setRowCount(5)
     
        self.widg.layout().addWidget(self.table)
        self.widg.layout().addWidget(self.wTools)
        self.setCentralWidget(self.widg)
     
      def setActions(self):
        self.quitAct =  QtGui.QAction(QtGui.QIcon(os.path.dirname(__file__)+"\\png\\exit.png"), "&Quitter",
          self, shortcut=QtGui.QKeySequence.Quit,
          statusTip="Quitter", triggered=QtGui.qApp.closeAllWindows)
     
      def setMenu(self):
        self.fileMenu = self.menuBar().addMenu("&Commandes")
        self.fileMenu.addAction(self.quitAct)
     
     
      def startServeur(self):
        self.webSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.thServeur = ThreadServeur(self)
        #self.connect(self.thServeur, QtCore.SIGNAL("newConnexion(PyQt_PyObject)"), self.newConnexion)
        self.thServeur.start()
     
      #def newConnexion(self, obj):
      #  r = self.table.rowCount()
      #  login , adresse, port = obj
      # # print "new!"
      #  self.table.insertRow(r)
      #  self.table.setItem(r , 0, QtGui.QTableWidgetItem(login))
      #  self.table.setItem(r , 1, QtGui.QTableWidgetItem(adresse))
      #  self.table.setItem(r , 2, QtGui.QTableWidgetItem(port))
     
     
    if __name__=="__main__":
      app = QtGui.QApplication(sys.argv) 
      ui = WidgServeur()
      ui.show()
     
      sys.exit(app.exec_())

  2. #2
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2010
    Messages
    140
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2010
    Messages : 140
    Points : 182
    Points
    182
    Par défaut
    Question bête :

    n'est il pas possible de faire un select * sur la membase usée et de remettre tout dans une base normale (postgres / mysql / mongo ...)
    une fois l'extract fait, faire un driver de rétro compatibilité comme le protocole ne semble pas trop compliqué (de ce qui est présenté)
    continuer sur un système plus accessible .

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Août 2009
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 195
    Points : 156
    Points
    156
    Par défaut
    Bonjour

    merci de vous intéressez au sujet..

    Je pense pas vraiment comprendre votre idée..
    Migrer la base de données? Je peux faire une copie de notre base vers une solution sql sans trop de soucis, mais ça ne reste qu'un reflet de notre base de données à un instant t.
    Je souhaite de l’accès temps réel.

    Approfondissez si j'ai pas bien compris.

    Merci

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 281
    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 281
    Points : 36 768
    Points
    36 768
    Par défaut
    Salut,

    Il y a plein de sujets intéressants dans votre post.

    Pour l'instant, je retiens ces interrogations:
    Citation Envoyé par Nico_tournai Voir le message
    ... c'est là que je bloque dans la réflexion.
    En passant par un model (QAbstractTableModel) qui se base sur mon tableau?
    Et à coup de SIGNAL pour rafraichir ma table?
    Mais où? par les threadClients? par un timer?
    Ce genre de question n'est pas facile a traiter lorsqu'on a le nez dans le code. Si on résume, on a:
    • un serveur qui fait "proxy" entre des connexions client et membase,
    • un outil d'administration qui affiche des informations sur ce qui se passe "dans" le serveur (et plus mais plus particulièrement l’état des connexions client).

    La View n'affiche que l’état du "Model".
    Comme les connexions s'ouvrent et se ferment, il va falloir "rafraîchir" ce "model". Ou plutôt indiquer a la View qu'une connexion a été ajoutée/supprimée afin que l'affichage (la View) se mette a jour.
    Si la "view" affiche les connexions dans l'ordre de création, on ajoutera a la fin et on supprimera n'importe ou.
    On a 2 "slots" a ajouter au "model":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        def append(self,....):
              ix = index de la derniere ligne,
              self.beginInsertRows(QModelIndex(), ix, ix)
              ... ajout de la row quelque part.
              self.endInsertRows()
     
        def remove(self,....):
              ix = index de la ligne a supprimer
              self.beginRemoveRows(QModelIndex(), ix, ix)
              ... suppression
              self.endRemoveRows()
    La question de savoir si on récupére l’état de l'ensemble des connexions pour effectuer les mises a jour ou si on le fait aux créations/destructions aboutira toujours l'appel ces slots.
    Si le serveur et le GUI sont effectivement des threads d'un même process (je ne suis pas sur que ce soit une bonne idée mais bon...) on peut éviter de dupliquer i.e. remonter dans la "view" les attributs des instances des connexions.

    Si c'est pas trop clair, je peux vous proposer un exemple de code.

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

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Août 2009
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 195
    Points : 156
    Points
    156
    Par défaut
    Bonjour wiztricks

    Je suis de Passage rapidement sur le forum. Achat cadeaux Saint Nicolas oblige!(Belgique)
    Effectivement il faut gérer les connexions/déconnexions (entre autres)... Il y a du boulot!

    Je reviens lundi sur le sujet.

    Merci!

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Août 2009
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 195
    Points : 156
    Points
    156
    Par défaut
    Re,

    Pour le moment, à chaque mouvement côté thread du client, j'envoie un signal (peut être pas le bon) pour ré-afficher.
    Le model se base sur un tableau de threads clients, auquel chaque thread a ses propres infos (nb requete, heure 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
    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
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
     
    # -*- coding: utf-8 -*- 
    import socket
    import sys
    import binascii
    import os
    import threading
    from PyQt4 import QtGui
    from PyQt4 import QtCore
     
    WEB_PORT = 5002
     
     
    MEMFILE_PORT = 5001
    MEMFILE_HOST = '192.168.0.205'
     
    class modelClient(QtCore.QAbstractTableModel):
      def __init__(self, parent=None):
        super(modelClient,self).__init__(parent)
        self.parent = parent
        self.columns = ["Nom", "Session", "Heure connexion","Requetes envoyees", "Requetes recues"]
     
      def headerData(self, section, orientation, role = QtCore.Qt.DisplayRole):
        if role != QtCore.Qt.DisplayRole:
          return QtCore.QVariant()
        if orientation == QtCore.Qt.Horizontal:
          return QtCore.QVariant(self.columns[section])
        return QtCore.QVariant(int(section + 1))
     
      def rowCount(self, index = QtCore.QModelIndex()):
        return len(self.parent.clients)
     
      def columnCount(self, index = QtCore.QModelIndex()):
        return len(self.columns)
     
      def data(self, index, role = QtCore.Qt.DisplayRole):
        r, c = index.row() , index.column()
        th = self.parent.clients[r]
        infos = [th.login, str(th.session),th.heure_connex , th.nb_req_envoi,th.nb_req_recu]
        if role == QtCore.Qt.DisplayRole :
          return QtCore.QVariant(infos[c])
        if role == QtCore.Qt.EditRole:
          return QtCore.QVariant(infos[c])
        return QtCore.QVariant()
     
     
     
    class ThreadClient(QtCore.QThread):
      def __init__(self, conn, parent=None):
        super(ThreadClient, self).__init__()
        self.parent = parent
        self.conn_web = conn    # Connexion web
        self.login = self.conn_web.recv(1024)      # Login
        self.nb_req_envoi = 0   # Nbre requete vers web
        self.nb_req_recu  = 1   # Nbre requete du web
        self.heure_connex = QtCore.QTime.currentTime() # Heure d'inscription
        self.connex_Memfile()
     
      def connex_Memfile(self): # Connexion serveur Memfile
        self.conn_mf = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        stream_c = '500060000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000530000'
        try:
          self.conn_mf.connect((MEMFILE_HOST, MEMFILE_PORT))
          self.conn_mf.send(binascii.unhexlify(stream_c))
          rec = self.conn_mf.recv(1024)
          session = rec[16:17]
          self.session = binascii.hexlify(session)
          self.conn_web.send(rec)
          self.nb_req_envoi +=1
          #self.emit(QtCore.SIGNAL("layoutChanged()"))
          self.parent.model.emit(QtCore.SIGNAL("layoutChanged()"))
        except :
          print 'erreur de connexion'
     
      def run(self):
        while True:
          msgWeb = self.conn_web.recv(5120)
          self.nb_req_recu +=1
          self.conn_mf.send(msgWeb)         # envoi au serveur memfile
          rep = self.conn_mf.recv(5120)     # reception du serveur memfile
          self.conn_web.send(rep)           # envoi reponse au web
          self.nb_req_envoi +=1
          self.parent.model.emit(QtCore.SIGNAL("layoutChanged()"))
     
     
     
    class ThreadServeur(QtCore.QThread):
      def __init__(self, parent):
        super(ThreadServeur, self).__init__()
        self.parent  = parent
        try:
          self.parent.webSocket.bind(('localhost',WEB_PORT))
          self.parent.webSocket.listen(5)
        except socket.error:
          print "erreur liaison socket"
     
      def run(self): # socket connexion web
        while True:
          connexion, adresse = self.parent.webSocket.accept()
          print adresse
          th = ThreadClient(connexion, self.parent)
          self.parent.clients.append(th)
          th.run()
     
     
    class WidgServeur(QtGui.QMainWindow):
      def __init__(self, parent=None):
        super(WidgServeur, self).__init__(parent)
        self.setup()
        self.clients = []
     
      def setup(self):
        self.statusBar().showMessage(u'')
        self.setActions()
        self.setMenu()
        self.widg = QtGui.QWidget() #------------------  Widget central
        self.widg.setLayout(QtGui.QHBoxLayout())   
        self.wTools = QtGui.QWidget() #----------------  Barre outils 
        self.wTools.setLayout(QtGui.QVBoxLayout())
        self.wTools.setFixedWidth(100)
        self.butStart = QtGui.QPushButton('Start!')
        self.butStart.clicked.connect(self.startServeur)
        self.butRefresh = QtGui.QPushButton('refresh!')
        self.butRefresh.clicked.connect(self.refresh)
        self.butOptions = QtGui.QPushButton('Options')
        self.butQuit = QtGui.QPushButton('Quitter')
     
        self.wTools.layout().addWidget(self.butStart)
        self.wTools.layout().addSpacing(40)
        self.wTools.layout().addWidget(self.butRefresh)
        self.wTools.layout().addWidget(self.butOptions)
        self.wTools.layout().addStretch()
        self.wTools.layout().addWidget(self.butQuit)
        self.table = QtGui.QTableView() #------------  Table 
        #self.table.setMinimumWidth(500)
        #self.table.setMinimumHeight(300)
        #self.table.setColumnCount(3)
        #self.table.setHorizontalHeaderLabels(["Session","Connexion","Derniere activite"])
        #self.table.setRowCount(5)
     
        self.widg.layout().addWidget(self.table)
        self.widg.layout().addWidget(self.wTools)
        self.setCentralWidget(self.widg)
     
      def setActions(self):
        self.quitAct =  QtGui.QAction(QtGui.QIcon(os.path.dirname(__file__)+"\\png\\exit.png"), "&Quitter",
          self, shortcut=QtGui.QKeySequence.Quit,
          statusTip="Quitter", triggered=QtGui.qApp.closeAllWindows)
     
      def setMenu(self):
        self.fileMenu = self.menuBar().addMenu("&Commandes")
        self.fileMenu.addAction(self.quitAct)
     
     
      def startServeur(self):
        self.webSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.thServeur = ThreadServeur(self)
        #self.connect(self.thServeur, QtCore.SIGNAL("newConnexion(PyQt_PyObject)"), self.newConnexion)
        self.model = modelClient(self)
        self.table.setModel(self.model)    
     
        self.thServeur.start()
     
     
     
      def refresh(self):
        self.model.emit(QtCore.SIGNAL("layoutChanged()"))
        #for th in self.clients:
        #  print th.
     
      #def newConnexion(self, obj):
      #  r = self.table.rowCount()
      #  login , adresse, port = obj
      # # print "new!"
      #  self.table.insertRow(r)
      #  self.table.setItem(r , 0, QtGui.QTableWidgetItem(login))
      #  self.table.setItem(r , 1, QtGui.QTableWidgetItem(adresse))
      #  self.table.setItem(r , 2, QtGui.QTableWidgetItem(port))
     
     
    if __name__=="__main__":
      app = QtGui.QApplication(sys.argv) 
      ui = WidgServeur()
      ui.show()
     
      sys.exit(app.exec_())
    Quand je lance une session web (en local) pour tester, ca fonctionne.
    A la deuxième session, j'ai pas de deuxieme ligne.. L'impression que la socket utilisée par mon navigateur reste la même que la première session...


    Est ce que je pars du bon pied?

    Je jongle avec des threads, des sockets, j'ai peur de m'y perdre (sans compter le php côté web que j'apprends)
    Toute aide/critique est la bienvenue

    Au bout de tout ca, j'aurais appris pas mal de choses

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 281
    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 281
    Points : 36 768
    Points
    36 768
    Par défaut
    Salut,

    Citation Envoyé par Nico_tournai Voir le message
    Est ce que je pars du bon pied?

    Je jongle avec des threads, des sockets, j'ai peur de m'y perdre (sans compter le php côté web que j'apprends)
    Toute aide/critique est la bienvenue
    Si vous déjà avez le sentiment de "jongler avec la peur de vous perdre", c'est pas très bon. De plus, vous montrez du code que nous pouvons lire certes, mais pouvoir le faire tourner serait bien plus intéressant.

    Intuitivement, il faut découper le problème en morceaux indépendants, partons avec GUI et serveur.

    Le serveur doit expédier au GUI les mises a jour des connexions clients. Une connexion est représentée par les attributs: login, session, heure_connex, nb_req_envoi, nb_req_recu,... d'une instance de...

    Inutile qu'une connexion soit "vraie" pour tester que le GUI affiche de nouvelles connexions, la mise a jour des valeurs, ...

    Après j'ai un soucis de "structure".
    Intuitivement, si on regarde le truc de loin, on devrait avoir un "main" qui lance le serveur et le GUI. Le serveur ne devrait connaître que l'interface qui lui permettra de mettre a jour le "modèle".
    Le GUI ne devrait connaître que l'interface qui lui permettra d’expédier des commandes au serveur.
    En gros, on devrait avoir ce "tissage":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def main():
          server = create_server(...)
          gui = create_gui(...)
          server.set_model (gui.model)
          gui.set_server(server.console)
          gui.exec()
    En fouillant un peu, le code que vous postez, réalise ce tissage. Mais difficile de mettre au point "serveur" et "GUI" indépendamment l'un de l'autre.

    Pour l'instant, je vous laisse touiller sur ces sujets.

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

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Août 2009
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 195
    Points : 156
    Points
    156
    Par défaut
    je touille je touille

    Bon, avant de me lancer avec des echanges avec mon serveur, je reprends les bases :
    - Un serveur basique en mode console
    serveur.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
     
    # -*- coding: utf-8 -*- 
    import socket
    import threading
    import sys
     
    WEB_PORT = 5002
     
    class ThreadClient(threading.Thread):
      def __init__(self, conn, port = 0):
        super(ThreadClient, self).__init__()
        # Connexion web
        self.conn_web = conn
        self.port = port
     
      def run(self):
        print "serveur start"
        while True:
          msgWeb = self.conn_web.recv(1024) # reception message web
          print 'Port %s: %s' %(self.port, msgWeb)
     
     
    web_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
      web_socket.bind(('localhost',WEB_PORT))
    except socket.error:
      print "erreur liaison socket"
      sys.exit()
    print "serveur ok"
    web_socket.listen(5)
     
    conn_client = {}
     
    while True:
      connexion, adresse = web_socket.accept()
      #login = connexion.recv(1024) # reception identifiant
      th = ThreadClient(connexion, adresse[1])
      th.start()
      it = th.getName()
      conn_client[it] = connexion
      print "Client %s connecté, adresse IP %s, port %s." %(it, adresse[0], adresse[1])
    - un client basique
    wclient.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
     
    # -*- coding: utf-8 -*- 
    import socket
    import sys
    import os
    from PyQt4 import QtGui
    from PyQt4 import QtCore
     
    WEB_PORT = 5002
     
    class WClient(QtGui.QWidget):
      def __init__(self, parent = None):
        super(WClient, self).__init__(parent)
        self.setLayout(QtGui.QVBoxLayout())
        self.linMsg = QtGui.QLineEdit()
        self.butSend = QtGui.QPushButton('Send')
        self.butSend.clicked.connect(self.sendMsg)
     
        self.layout().addWidget(self.linMsg)
        self.layout().addWidget(self.butSend)
     
        self.webSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
          self.webSocket.connect(('localhost',WEB_PORT))
        except:
          print "erreur client"
          sys.exit()
     
      def sendMsg(self):
        msg = str(self.linMsg.text())
        self.webSocket.send(msg)
     
    if __name__=="__main__":
      app = QtGui.QApplication(sys.argv) 
      ui = WClient()
      ui.show()
      sys.exit(app.exec_())
    En lançant le serveur au préalable, suivi de un ou des clients, ca fonctionne...

    MAINTENANT, ce serveur en mode graphique où la partie serveur est dans un thread:
    wserveur.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
    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
     
    # -*- coding: utf-8 -*- 
    import socket
    import sys
    import os
    from PyQt4 import QtGui
    from PyQt4 import QtCore
     
    WEB_PORT = 5002
    CLIENTS = []
     
    class modelClient(QtCore.QAbstractTableModel):
      def __init__(self, parent=None):
        super(modelClient,self).__init__(parent)
        self.parent = parent
        self.columns = ["PORT", "Message"]
     
      def headerData(self, section, orientation, role = QtCore.Qt.DisplayRole):
        if role != QtCore.Qt.DisplayRole:
          return QtCore.QVariant()
        if orientation == QtCore.Qt.Horizontal:
          return QtCore.QVariant(self.columns[section])
        return QtCore.QVariant(int(section + 1))
     
      def rowCount(self, index = QtCore.QModelIndex()):
        return len(CLIENTS)
     
      def columnCount(self, index = QtCore.QModelIndex()):
        return len(self.columns)
     
      def data(self, index, role = QtCore.Qt.DisplayRole):
        r, c = index.row() , index.column()
        th = CLIENTS[r]
        infos = [th.port, th.msg]
        if role == QtCore.Qt.DisplayRole :
          return QtCore.QVariant(infos[c])
        if role == QtCore.Qt.EditRole:
          return QtCore.QVariant(infos[c])
        return QtCore.QVariant()
     
     
    class ThreadClient(QtCore.QThread):
      def __init__(self, conn, parent = None, port=0):
        super(ThreadClient, self).__init__()
        self.parent = parent
        self.conn_web = conn    # Connexion web
        self.port = port
        self.msg = ''
     
      def run(self):
        while True:
          self.msg = self.conn_web.recv(1024)
          self.parent.model.emit(QtCore.SIGNAL("layoutChanged()"))
     
     
    class ThreadServeur(QtCore.QThread):
      def __init__(self, parent):
        super(ThreadServeur, self).__init__()
        self.parent  = parent
        self.webSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
          self.webSocket.bind(('localhost',WEB_PORT))
          self.webSocket.listen(5)
        except socket.error:
          print "erreur liaison socket"
     
      def run(self):
        while True:
          connexion, adresse = self.webSocket.accept()
          print adresse[0], adresse[1]
          th = ThreadClient(connexion, self.parent, adresse[1])
          CLIENTS.append(th)
          th.run()
     
     
    class WServeur(QtGui.QWidget):
      def __init__(self, parent = None):
        super(WServeur, self).__init__(parent)
        self.setLayout(QtGui.QVBoxLayout())
        self.table = QtGui.QTableView()
        self.butStart = QtGui.QPushButton('Start')
        self.butStart.clicked.connect(self.startServeur)
        self.layout().addWidget(self.table)
        self.layout().addWidget(self.butStart)
     
      def startServeur(self):
        self.model = modelClient(self)
        self.table.setModel(self.model)
        self.thServeur = ThreadServeur(self)
        self.thServeur.start()
     
     
    if __name__=="__main__":
      app = QtGui.QApplication(sys.argv) 
      ui = WServeur()
      ui.show()
      sys.exit(app.exec_())
    Et là je n'ai qu'une connexion client qui se fait...
    Je passe à côté de quelque chose c'est sûr, merci à celui qui éclairera ma modeste lanterne

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 281
    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 281
    Points : 36 768
    Points
    36 768
    Par défaut
    Citation Envoyé par Nico_tournai Voir le message
    Et là je n'ai qu'une connexion client qui se fait...
    Je passe à côté de quelque chose c'est sûr, merci à celui qui éclairera ma modeste lanterne
    Le + est qu'on peut voir ce qu'il se passe.
    Le - est que sans construire sur des codes qui fonctionnent, on s'enlise...

    Le "bug" constate est la:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class ThreadServeur(QtCore.QThread):
      ...
      def run(self):
        while True:
          connexion, adresse = self.webSocket.accept()
          print adresse[0], adresse[1]
          th = ThreadClient(connexion, self.parent, adresse[1])
          CLIENTS.append(th)
          th.run()  #<---
    remplacez .run par .start

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

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Août 2009
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 195
    Points : 156
    Points
    156
    Par défaut
    Toujours les mêmes qui répondent

    Arf je l'avais pas vu celle là!

    Merci de prendre votre temps pour répondre à de nombreux sujets sur ce forum, je suis beaucoup vos interventions (et aussi sarcasmes parfois..)

    Je continue mes déboires, je reviendrais si besoin sur ce sujet

  11. #11
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut
    Bonjour,
    Je programme Membasic depuis 1987 et j'ai 1 assembly qui dialogue avec Mf2000 et me permet de lire/écrire dans 1 fichier Mf à partir de .Net.
    Ton travail a éveillé ma curiosité.
    Tu en es où ?

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Août 2009
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 195
    Points : 156
    Points
    156
    Par défaut
    Bonjour

    un programmeur membasic!

    Partant de rien, je me suis lancé à regarder les paquets sur le réseau vers le memfile, en faisant des opérations sur un fichier (open/close , write/update/delete , bornage ...).
    J'ai réussi à comprendre le mécanisme (non crypté ouf! sauf les paquets du nom de session qu'on retrouve dans le memfile qui changent (les paquets et non le nom) à chaque connexion)
    J'ai réussi à implémenter une classe qui communique avec le memfile, et faire des opérations sur fichier memfile.
    Tout ceci marche plutôt bien en test, mais pas encore vraiment testé en production (un chef de service assez fermé au monde exterieur... )
    On a plus ou moins 150 sessions qui tournent ici en memfile.
    Comment as tu eu ton assembly? par memsoft à l'époque?

  13. #13
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut
    on a fait comme toi, on l'a écrit en C#, sauf qu'on a les sources de Membasic donc ça nous a un peu aidé...

Discussions similaires

  1. [AC-2013] Conception d'une base de données dans le cadre d'une salle de sport
    Par h4cktaas dans le forum Modélisation
    Réponses: 5
    Dernier message: 14/10/2014, 13h36
  2. Réponses: 3
    Dernier message: 15/04/2012, 10h17
  3. Sauvegarder des données dans un fichier depuis une Base de Données
    Par ankou2005 dans le forum Contribuez / Téléchargez Sources et Outils
    Réponses: 0
    Dernier message: 14/02/2011, 18h51
  4. POSTer des données dans l'admin depuis une vue
    Par dchango dans le forum Django
    Réponses: 5
    Dernier message: 17/01/2011, 15h30
  5. Réponses: 19
    Dernier message: 15/05/2006, 21h52

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