Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 17
  1. #1
    Utente di HTML.it L'avatar di gianiaz
    Registrato dal
    May 2001
    Messaggi
    8,027

    [python] Passare dati ricevuti da socket a finestra wxpython

    Ciao, innanzi tutto scusate per il titolo, sto cominciando a guardare le wx python, e non mi destreggio molto...

    Sto cercando come esercizio di far comunicare 2 pc attraverso dei semplici messaggi passati tramite UDP.

    Ho letto questo articolo e messo in pratica quello che è spiegato.

    Ho seguito anche qualche tutorial riguardante le wxpython, creo la classe che estende WX.frame e metto nella finestra i controlli che voglio...

    Una cosa mi stavo chiedendo, come faccio a passare alle wx i messaggi che arrivano tramite UDP?

    Ho pensato di passare nel costruttore dell'applicazione l'oggetto socket, ma non so bene come fare... mi date una manina?

    grazie

  2. #2
    Ho letto questo articolo e messo in pratica quello che è spiegato.
    Quale articolo?

    Una cosa mi stavo chiedendo, come faccio a passare alle wx i messaggi che arrivano tramite UDP?
    Ho pensato di passare nel costruttore dell'applicazione l'oggetto socket, ma non so bene come fare... mi date una manina?
    Non ho ben capito la domanda.
    Non sai come strutturare la cosa o non sai proprio come passare l'oggetto socket alla classe della GUI?
    Nel secondo caso, banalmente:

    codice:
    import socket 
    
    class gui:
        def __init__(self, udp_sock):
            self.udp_sock = udp_sock
    
    udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    g = gui(udp_sock)
    g.loop()
    ...anche se forse lavorare con l'ggetto socket 'grezzo' non è il massimo.
    Un framework (es: asyncore) con con sviluppare una classe separata in cui ti occupi della sola connessione UDP potrebbe essere, forse, una scelta più azzeccata.
    Tutto cmq dipende dall'applicazione.
    Dai più info magari...
    Rilasciata Python FTP Server library 0.5.1
    http://code.google.com/p/pyftpdlib/

    We'll be those who'll make the italian folks know how difficult can be defecating in Southern California without having the crap flying all around the house.

  3. #3
    Utente di HTML.it L'avatar di gianiaz
    Registrato dal
    May 2001
    Messaggi
    8,027
    Originariamente inviato da billiejoex
    Quale articolo?
    sorry, questo: http://evolt.org/node/60276

    c'ho 38 di febbre, capitemi...

    Non ho ben capito la domanda.
    Non sai come strutturare la cosa o non sai proprio come passare l'oggetto socket alla classe della GUI?
    Nel secondo caso, banalmente:

    codice:
    import socket 
    
    class gui:
        def __init__(self, udp_sock):
            self.udp_sock = udp_sock
    
    udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    g = gui(udp_sock)
    g.loop()
    Ok, era questo che intendevo...
    ...anche se forse lavorare con l'ggetto socket 'grezzo' non è il massimo.
    Un framework (es: asyncore) con con sviluppare una classe separata in cui ti occupi della sola connessione UDP potrebbe essere, forse, una scelta più azzeccata.
    Tutto cmq dipende dall'applicazione.
    Dai più info magari...
    L'applicazione è quella che ipotizzavo qui:

    http://forum.html.it/forum/showthrea...5#post10247805

    Sinceramente non conosco molto python, quindi non conosco il framework di cui parli...

    Grazie, ciao

  4. #4
    Utente di HTML.it L'avatar di gianiaz
    Registrato dal
    May 2001
    Messaggi
    8,027
    Ciao, sono ancora qui, ho un po' di problemi, ti posto ciò che ho scritto fin'ora:

    Codice Che andrà sul client windows XP:

    codice:
    #!/usr/bin/env python
    import wx
    import wx.html
    import sys
    from socket import *
    
    class Frame(wx.Frame):
      def __init__(self,s,parent, id, title):
        print "Frame __init__"
        
        dlg = wx.MessageDialog(None, 'Procedo con il backup?', 'Caladan Backup Utility', wx.YES_NO | wx.ICON_QUESTION)
        result = dlg.ShowModal()
        dlg.Destroy()
        if(result == wx.ID_YES): 
            window_width = 300;
            window_height = 200;
            wx.Frame.__init__(self, parent, id, title, (0,0),(window_width,window_height))
            
            status = self.CreateStatusBar(2, 0, id);
            status.SetStatusText('gianiaz.net (C)')
            status.SetStatusText('giovanni b lenoci', 1)
            panel = wx.Panel(self);
            panel.SetBackgroundColour('White')
            self.html = wx.html.HtmlWindow(self, -1, pos=wx.DefaultPosition,size=(295, 150))
            self.setHTML('prova');
    
        else:
          self.Close()
          
      def setHTML(self, html):
          self.html.SetPage(html)
    
      def OnCloseMe(self, event):
        self.Close(True)
      
      def OnCloseWindow(self, event):
        self.Destroy()    
    
    class messageReceived(wx.PyCommandEvent):
      def __init__(self, evtType, id):
        wx.PyCommandEvent.__init__(self, evtType, id)
    
    class App(wx.App):
      def __init__(self, s, redirect=True, filename=None):
        self.s = s;
        print s;
        wx.App.__init__(self, redirect, filename)
      def OnInit(self):
        print "OnInit"
        self.frame = Frame(s=self.s, parent=None, id=1, title='Startup')
        self.frame.Show()
        self.SetTopWindow(self.frame)
        return True
    
      def OnExit(self):
        print "OnExit"
    
    if __name__ == '__main__':
        host = "localhost"
        port = 21567
        buf = 1024
        addr = (host,port)
        UDPSock = socket(AF_INET,SOCK_DGRAM)
        UDPSock.bind(addr)
        data,addr = UDPSock.recvfrom(buf)
        # Receive messages
        while 1:
          data,addr = UDPSock.recvfrom(buf)
          print data
          if data:
            if(data == 'open') :
              opened = True
              app = App(redirect=False, filename=None, s=UDPSock)
              app.MainLoop()
              print 'hai chiuso la finestra'
              UDPSock.close()
              break
    e quello sul server che manderà dei messaggi al client

    codice:
    #!/usr/bin/env python
    import sys
    from socket import *
    
    
    
    host = "localhost"
    port = 21567
    buf = 1024
    addr = (host,port)    
    UDPSock = socket(AF_INET,SOCK_DGRAM)
    UDPSock.sendto('ping',addr)
    # Send messages
    while (1):
      data = raw_input('>> ')
      if not data:
          break
      else:
          if(UDPSock.sendto(data,addr)):
              print "Sent :",data
      # Close socket
    UDPSock.close()
    Ovviamente il codice è da sistemare, e non va ancora nulla...

    Il problema che vorrei risolvere al momento è ricevere il messaggio sulla finestra.
    Avevo pensato di mettere una finestra html e far passare dei messaggi.

    Ma subito dopo l'init, sembra che i dati non arrivino più (ho provato a mettere un print data).

    Probabilmente la mia scarsa conoscenza delle wxpython mi manda in confusione.
    Penso che il problema sia che dopo l'init, mi trovo all'interno del Mainloop, quindi non ricevo più i dati.
    Come dovrei fare?
    Creare un evento che viene scaturito all'arrivo di un messaggio?
    In tal caso dove verifico l'arrivo del messaggio?
    Mi viene stupidamente da pensare che dovrei far arrivare la socket al mainloop, e da li verificare che sia arrivato qualcosa...

    Anche se sono lontano dalla soluzione potete darmi qualche riferimento su cosa studiare per chiudere il cerchio?

    ciao e grazie

  5. #5
    L'applicazione è quella che ipotizzavo qui:
    http://forum.html.it/forum/showthre...05#post10247805
    ok.

    Sinceramente non conosco molto python, quindi non conosco il framework di cui parli.
    Lascia perdere. Per quello che devi fare puoi benissimo usare il modulo socket, a questo punto.

    Ovviamente il codice è da sistemare, e non va ancora nulla...
    Il problema che vorrei risolvere al momento è ricevere il messaggio sulla finestra.
    Come dovrei fare?
    Creare un evento che viene scaturito all'arrivo di un messaggio?
    In tal caso dove verifico l'arrivo del messaggio?
    Posso darti un consiglio strutturale ma non del codice vero e proprio dato che richiede un po' di tempo di cui al momento non dispongo.
    La soluzione che userei io è la seguente:

    - crei una class "gui" relativa all'interfaccia.
    - crei una class "connection" relativa alla connessione.
    - inizializzi la classe "gui" dalla quale:
    -- inizializzi la classe "connection" alla quale passi come parametro l'istanza della classe "gui" stessa ("self"). Allo stesso tempo mantieni un riferimento all'istanza "gui" che hai appena creato. In parole povere qualcosa del tipo: "self.conn_instance = connection(self)".
    - quando nella classe "connection" ti arrivano dei dati richiami un metodo della classe "gui" che pop-upperà' un messaggio.
    - quando dalla classe GUI vorrai spedire dei dati richiamerai l'apposito metodo della classe "connection" tramite l'attributo "self.conn_instance" che conterrà l'istanza della classe "connection".

    Il codice che ti incollo è molto povero ma è giusto per farti capire come io strutturei la cosa:

    codice:
    class gui:
        
        def __init__(self):
            self.connection_instance = connection(self)
    
        def OnMsgReceived(self, msg):
            # qui fai apparire un pop-up
    
        def manda_messaggio(self, msg=''):
            # self.connection_instance.send('hi there')
        
    class connection:
        
        def __init__(self, gui_instance):
            self.gui_instance = gui_instance
            # crea socket
            # se ci sono dati da ricevere:
            #      self.OnDataReceived()
    
        def OnDataReceived(self):
            self.gui_instance.OnMsgReceived()
    
        def send(self, msg):
            # oggetto_socket.send(destinazione, messaggio)
    Ci sono altri aspetti che meriterebbero di essere menzioati come ad esempio:
    - i socket UDP non bloccanti che sei obbligato ad usare in quanto applicazione di messaggistica.
    - prestare attenzione al riferimento circolare che viene a crearsi nel garbage collector utilizzando "self.gui_instance = gui_instance".

    ...ma sono cose di cui si può discutere anche in un secondo momento.
    Rilasciata Python FTP Server library 0.5.1
    http://code.google.com/p/pyftpdlib/

    We'll be those who'll make the italian folks know how difficult can be defecating in Southern California without having the crap flying all around the house.

  6. #6
    Utente di HTML.it L'avatar di gianiaz
    Registrato dal
    May 2001
    Messaggi
    8,027
    ti chiedo un'altra cosa, leggendo i vari articoli, ho visto che per ricevere i dati da una porta udp viene messo tutto in un ciclo cosi:

    while 1:
    data, addr = socket.recv(1024)
    if data:
    print data



    Io mi sono scritto la classe che fa la connessione, nell'init apro la porta socket, e poi ho pensato che debba stare in ascolto, e cosi ho fatto un metodo chiamato MainLoop dove ho messo il pezzo di codice soprastante.

    In questo modo però perdo il controllo del programma e inoltre posso solo ricevere e non spedire.

    Come ci si comporta in questi casi?
    Leggevo qualcosa riguardo i thread, è forse questa la strada da seguire?

    ciao e grazie per la pazienza

  7. #7
    No, devi utilizzare socket non bloccanti. socket_obj.recv() si comporta esattamente come una sleep. Finchè non ricevi dati ti blocca tutto il programma.
    Mettendo un timeout sul socket ("socket_object.settimeout()") la recv() ritorna anche se non sono arrivati dati.
    All'interno del ciclo while dovresti controllare se vi sono dati ricevuti o dati da mandare (inserendoli all'interno di un buffer) e comportarti di conseguenza.
    Tutto questo puoi farlo utilizzando varie metodologie:
    - manualmente operando con l'oggetto socket posto all'interno di un ciclo while (guarda esempio di codice che ti ho incollato sotto).
    - manualmente utilizzando select()/poll().
    - lavorando a livelli più alti utilizzando un framework (asyncore, asynchat, twisted).

    Il tuo problema, nello specifico, si complica un po' dato che oltre a questo devi occuparti anche della GUI. In questo caso, probabilmente, trattare una delle due classi all'interno di un thread a parte potrebbe accomodarti di molto il lavoro, anche se la maniera 'fina' di fare il tutto sarebbe quella di utilizzare un unico thread/processo asincrono sia per la gui che per la connessione (ma come ti ho gia detto, di GUI non sono pratico quindi in questo senso non saprei come consigliarti).

    codice:
    # semplice echo server UDP
    import socket
    
    host = ''
    port = 1234
    
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.bind((host, port))
    s.settimeout(0.1)
    print "serving on port: %s" %port
    
    in_data = ''
    out_data = ''
    
    while 1:
        try:
            in_data, address = s.recvfrom(8192)
        except socket.timeout:
            pass     
        if in_data:
            print "%s <== %s" %(address, in_data)
            out_data = in_data
        if out_data:
            s.sendto(out_data, address)
        # 'flushing' dei due buffer
        in_data = out_data = ''
    Rilasciata Python FTP Server library 0.5.1
    http://code.google.com/p/pyftpdlib/

    We'll be those who'll make the italian folks know how difficult can be defecating in Southern California without having the crap flying all around the house.

  8. #8
    Utente di HTML.it L'avatar di gianiaz
    Registrato dal
    May 2001
    Messaggi
    8,027
    grazie mille, anche se sto approcciando in modo un po' maccheronico mi stai aprendo a capire diverse cose.

    alla prox

  9. #9
    Eh beh all'inizio si arranca sempre.
    Tieni aggiornato il thread che mi interessa il tipo di applicazione.
    Rilasciata Python FTP Server library 0.5.1
    http://code.google.com/p/pyftpdlib/

    We'll be those who'll make the italian folks know how difficult can be defecating in Southern California without having the crap flying all around the house.

  10. #10
    Utente di HTML.it L'avatar di gianiaz
    Registrato dal
    May 2001
    Messaggi
    8,027
    ciao, ho avuto poco tempo di testare, nel frattempo ho messo in piedi il server, e ho provato lo script per quanto riguarda la comunicazione di rete.

    il codice è questo :

    codice:
    #!/usr/bin/python
    
    import socket
    import time
    
    host = '192.168.0.10';
    port_rec = 21568
    port_send = 21568
    buf = 1024
    
    class connection:
    
        def __init__(self, gui_instance):
            self.s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
            self.addr_rec = ('localhost',port_rec)
            self.addr_send = (host, port_send)
            self.s.bind(self.addr_rec)
            self.s.settimeout(0.1)
            self.gui_instance = gui_instance
            # crea socket
            # se ci sono dati da ricevere:
            #      self.OnDataReceived()
            print "Server in ascolto : ", self.addr_rec
            self.MainLoop()
    
        def MainLoop(self):
            start = time.time()
            while 1:
                data = ''
                try:
                  data, addr = self.s.recvfrom(buf)
                except socket.timeout:
                  pass
                if data :
                  pass
    
                if(time.time() > (start+5)):
                  self.send('Are you online?')
                  start = time.time()
    
    
        def OnDataReceived(self):
            self.gui_instance.OnMsgReceived()
    
        def send(self, msg):
            print "invio a :", self.addr_send," del messaggio :", msg
            self.s.sendto(msg,self.addr_send)
            self.s.sendto(msg,self.addr_send)
    
    conn = connection('prova')
    finchè facevo partire 2 script cosi, con le porte incrociate per simulare 2 pc funzionava correttamente.

    Quando ho cambiato il valore di host nell'ip che vedi nel codice ricevo questo errore dopo i primi 5 secondi:
    codice:
    Server in ascolto :  ('localhost', 21568)
    invio a : ('192.168.0.10', 21568)  del messaggio : Are you online?
    Traceback (most recent call last):
      File "./backup_server.py", line 49, in <module>
        conn = connection('prova')
      File "./backup_server.py", line 24, in __init__
        self.MainLoop()
      File "./backup_server.py", line 38, in MainLoop
        self.send('Are you online?')
      File "./backup_server.py", line 47, in send
        self.s.sendto(msg,self.addr_send)
    socket.error: (22, 'Invalid argument')
    Dici che è un problema di python o qualcosa che ignoro?

    Ho provato sia con la versione 2.4 che con la 2.5 su linux.

    ciao

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.