Forum
>>
Principianti
>>
Utilizzo Socket
Pagina: Indietro 1 2 3 4 5 6 Avanti
Esegui il login per scrivere una risposta.
Pagina: Indietro 1 2 3 4 5 6 Avanti
Scritto da nuzzopippo |
2024-02-24 14:56:58 - Re: Utilizzo Socket
|
È mia opinione che condividere la conoscenza sia sempre bene, da un lato rende informazioni,magari ottenute con fatica, fruibili agli altri, d'altro lato può spingere a suggerimenti circa eventuali miglioramenti. Comunque, rappresentano un momento di crescita condivisa.
Avevo già letto il Tuo "consigliami", la risposta è scontata : tkinter.text + scrollbars ... per me è facile da realizzare ma il primo pensiero che mi è venuto in mente è stato : e mo' come gli spiego come si fa? Ho già realizzato un sub-classamento della classe tkinter.Text che si auto-limita ad un numero di linee di testo definito dall'user e che può o meno essere modificabile senza essere disabilitata (nel mio linux una tkinter.Text disabilitata come aspetto fa piangere), una volta completati i test e collegata al codice utilizzato per esemplificare con lo echo-server che ho usato post fa, fornirò qui le istruzioni per inserire la sub-classe nella Tua applicazione e su di un sito più comodo le spiegazioni sul suo funzionamento, ci sono diverse cose da tener presenti in merito alla implementazione. Sempre in ambito "consigliami": Le classi sono inevitabili parlando di GUI, cerca di comprenderle, il tutorial è un buon inizio, principalmente se lo condisci con la documentazione, relativamente a tkinter, necessiterai di molte ricerche in rete, comunque la documentazione meglio organizzata a mio parere è quella sulla versione 8.5, un po' vecchiotta ma molto utile ... sono "strumenti" che io uso quotidianamente, poi ci sono tante prove ed olio di gomito ... Fatti non foste a viver come bruti... |
|
Scritto da Pietro Bruno Lancerotto |
2024-02-24 20:05:53 - Re: Utilizzo Socket
|
Oggi ho messo sotto torchio il terminale
Diciamo che nell'ambito di utilizzo suo proprio non dovrebbe accadere mai .... però L'ho lasciato in ascolto sul canale APRS dei radioamatori e li arriva un po' di tutto ed è arrivato questo `''yl!rr/r7a & ru12a sysop IR3BT*,WIDE2-1 <UI pid=F0 Len=26 >[16:45:18] `''yl!rr/r7a & ru12a sysop IR3BT*,IK3SVW-11*,WIDE2* <UI pid=F0 Len=26 >[16:45:20] Che finché il decode ha "tenuto" ha dato questo 1:Fm IN3RIY To 4V0P20 Via IR3BT*,WIDE2-1 <UI pid=F0 Len=26 >[16:45:18] `''yl!rr/r7a & ru12a sysop 1:Fm IN3RIY To 4V0P20 Via IR3BT*,IK3SVW-11*,WIDE2* <UI pid=F0 Len=26 >[16:45:20] `''yl!rr/r7a & ru12a sysop Poi alla ricezione successiva è andato in errore Exception in thread Thread-1 (listen): Traceback (most recent call last): File "C:\Program Files\Python312\Lib\threading.py", line 1073, in _bootstrap_inner self.run() File "C:\Program Files\Python312\Lib\threading.py", line 1010, in run self._target(*self._args, **self._kwargs) File "D:\DRIVE-BRUNO\PYTHON\PROVE\PKT_GUI_RCS\utility.py", line 86, in listen msg = ['RECEIVED', data[36:-3].decode()] ^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf8 in position 144: invalid start byte Argghhh vale 248 decimale / è ° In un primo momento avevo pensavo alla lunghezza ma poi leggendo bene ... Un famigerato carattere oltre il 127 Secondo il mio punto di vista bisognerebbe prima tagliare il data e poi vedere se nella parte estrapolata ci sia un carattere > di 127 e saltare la decodifica Trovare UN carattere è una cosa ma in questo caso bisogna "ciclare" tutti i caratteri e se uno è sballato saltare il decode Questa la mia teoria ma metterla in pratica .... Mi è capitato di muovere il disco di una "bollinatrice" con 36 caratteri ( 1 ogni 10° ) posizionandola dopo aver interpretato il codice ASCII del testo, lettera per lettera. Ma in quel caso il linguaggio era un altro e non era Python Si puo' fare ?? --- Ultima modifica di Pietro Bruno Lancerotto in data 2024-02-24 20:19:24 --- --
Bruno L. |
|
Scritto da Pietro Bruno Lancerotto |
2024-02-25 08:47:26 - Re: Utilizzo Socket
|
Sto facendo qualche prova per togliere i caratteri da 128 a 255
string = "AAAÇüé°BBB" characters = "Ç°üé" for x in range(len(characters)): string = string.replace(charactersx, "") # ma perchè toglie le parentesi quadre ai lati di x print(string) In ogni caso io ho byte vedo cosa succede Ho modificato così msg = ['RECEIVED', data[36:-3].decode(encoding="UTF-8", errors="ignore")] --- Ultima modifica di Pietro Bruno Lancerotto in data 2024-02-25 10:21:58 --- --
Bruno L. |
|
Scritto da nuzzopippo |
2024-02-25 10:48:59 - Re: Utilizzo Socket
|
Prova a fare questo tentativo:
# implenta questa funzione nel modulo utility def read_message(data: bytes) -> str: return ''.join([chr(int.from_bytes(x, 'little')) for x in data[36:-3]]) #trasforma questa istruzione msg = ['RECEIVED', data[36:-3].decode()] #così msg = ['RECEIVED', read_message(data)]la funzione "dovrebbe" trasformare ogni singolo byte in un intero e poi nel carattere corrispondente, quindi unire tutto in stringa e restituire la stringa formata. Non la ho testata (appena sveglio e con poco tempo) ma penso dovrebbe funzionare, possibile variante sarebbe utilizzare "big" invece di "little", dipende dalla benedetta codifica con cui vengono trasmessi i dati, di certo molto oscura. Fai sapere, ciao EDIT : No, lascia perdere, non funziona il problema dovrebbe nascere dalla codifica di trasmissione, di certo non utf-8, vai ad ad indovinare che codifica viene utilizzata (forse la cp1252?) ... meglio la Tua soluzione di ignorare gli errori. Una variante potrebbe essere utilizzare esclusivamente il chr() ma darebbe caratteri impropri per gli utf-8 da due bytes ... forse bisognerebbe guardarsi la documentazione l'header scartato (i 36 bit) per vedere se vi è qualcosa riguardo alla codifica del messaggio. --- Ultima modifica di nuzzopippo in data 2024-02-25 10:50:44 --- --- Ultima modifica di nuzzopippo in data 2024-02-25 11:38:06 --- Fatti non foste a viver come bruti... |
|
Scritto da Pietro Bruno Lancerotto |
2024-02-25 18:26:49 - Re: Utilizzo Socket
|
Con la soluzione di ignorare gli errori sta andando da una decina di ore senza perdere un colpo; quasi 3000 righe di log.
Io sto provando connesso agli APRS che mandano un casino di caratteri strani Mi domando come il SM faccia passare certi pacchetti. Quando sarà usato per lo scopo per cui è nato ci saranno solo caratteri corretti e comunque le postazioni sono qualche decina di Km dalla prima all'ultima Il segnale è sempre molto forte per cui non c'è pericolo di invii farlocchi. Adesso dovrò ridimensionare un po' perchè è troppo grande.Nella parte TX vengono inviate 2 3 righe alla volta per cui và accorciata Grazie al tuo supporto sono arrivato in fondo --
Bruno L. |
|
Scritto da nuzzopippo |
2024-02-26 18:43:47 - Re: Utilizzo Socket
|
beh ... c'è ancora quel "consigliami" in ballo
Copia questo codice in "utility.py" import tkinter as tk class BufferedText(tk.Text): '''Una Text-box inibibile alla scrittura senza disabilitazione e che espone un numero stabilito di righe di testo.''' key_none = ['Alt_L', 'Alt_R', 'Caps_Lock', 'Control_L', 'Control_R', 'Down', 'End', 'Escape', 'Execute', 'F1', 'F2', 'Fi', 'F12', 'Home', 'Insert', 'Left', 'Linefeed', 'KP_Add', 'KP_Begin', 'KP_Divide', 'KP_Down', 'KP_End', 'KP_Home', 'KP_Insert', 'KP_Left', 'KP_Next', 'KP_Prior','KP_Right', 'KP_Up', 'Next', 'Num_Lock', 'Pause', 'Print', 'Prior', 'Right', 'Scroll_Lock', 'Shift_L', 'Shift_R', 'Tab', 'Up'] def __init__(self, parent: callable, active: bool=False, rowsize: int=0, *args, **kwargs) -> None: super().__init__(parent, *args, **kwargs) self.parent = parent self._active = active self._rowsize = rowsize if rowsize >=0 else 0 self._bg = self['background'] self.bind('<KeyPress>', self._on_key) self.bind('<FocusIn>', self._on_focus) self.bind('<FocusOut>', self._out_focus) def _on_key(self, evt: callable) -> None: if evt.keysym in ['Return', 'KP_Enter'] and self._rowsize: # valuta il caso si aggiunga una riga if not self._active: return 'break' self._evaluate_rows() elif not self._active and not evt.keysym in self.key_none: return 'break' def _evaluate_rows(self): if not self._rowsize: return rows = int(self.index('end').split('.')[0]) - 2 if self._active and self.parent.focus_get() == self: rows += 1 if rows > self._rowsize: # raggiunto il limite di righe stabilito for i in range(rows - self._rowsize): self.delete('1.0', '1.end + 1 char') self.update() def _on_focus(self, evt: callable) -> None: color = '#ffffc0' if self._active else '#bfe5f1' self.configure(bg=color) def _out_focus(self, evt: callable) -> None: self.configure(bg=self._bg) def is_active(self) -> bool: return self._active def activate(self) -> None: self._active = True def disable(self) -> None: self._active = False @property def buffer(self) -> int: return self._rowsize @buffer.setter def buffer(self, buff: int) -> None: self._rowsize = buff if buff >=0 else self._rowsize self._evaluate_rows() def add_text(self, text: str) -> None: self.insert('end', text) self._evaluate_rows() self.see('end')avrai disponibile un Text tkinter che potrai rendere a sola lettura senza disattivarlo e cui potrai porre un limite alle righe da visualizzare, per farlo edita il file "pkt_gui_rcs.py" inserendo questo import from utility import BufferedTextPoi modifica il punto con self.TESTO_RX in questo modo self.TESTO_RX = BufferedText(self.FrameRX, rowsize=200, height=5, wrap='none') #self.TESTO_RX.place(relx=0.005, rely=0.1, height=350, width=915) self.TESTO_RX.grid(row=1, column=0, padx=(5,1), pady=(5,1), sticky='nsew') '''self.TESTO_RX.configure(activebackground="#f9f9f9") self.TESTO_RX.configure(anchor='w') self.TESTO_RX.configure(background="#ffffec") self.TESTO_RX.configure(compound='left') self.TESTO_RX.configure(disabledforeground="#a3a3a3") self.TESTO_RX.configure(font="-family {Courier} -size 10") self.TESTO_RX.configure(foreground="black") self.TESTO_RX.configure(highlightbackground="#d9d9d9") self.TESTO_RX.configure(highlightcolor="black") self.TESTO_RX.configure(justify='left')''' vscroll = tk.Scrollbar(self.FrameRX, orient=tk.VERTICAL, command=self.TESTO_RX.yview) vscroll.grid(row=1, column=1, padx=(1,5), pady=(5,1), sticky='ns') self.TESTO_RX.configure(yscrollcommand=vscroll.set) hscroll = tk.Scrollbar(self.FrameRX, orient=tk.HORIZONTAL, command=self.TESTO_RX.xview) hscroll.grid(row=2, column=0, padx=(5,1), pady=(1,5), sticky='ew') self.TESTO_RX.configure(xscrollcommand=hscroll.set) #self.TESTO_RX.configure(textvariable=self.TestoRicevuto) #self.TestoRicevuto.set('''''') self.FrameRX.grid_columnconfigure(0, weight=1) self.FrameRX.grid_rowconfigure(1, weight=1)quindi modifica il metodo "obs" così def obs(self, message: list) -> None: op = message[0] txt = '' if op != 'ERROR': txt = message[1] self.TESTO_RX.add_text(txt + '\n') else: txt = 'AVVENUTO ERRORE : ' + message1 #old = self.TestoRicevuto.get() #txt = old + '\n'+ txt #self.TestoRicevuto.set(txt)Dovresti trovarTi una text-box che fa quello che mi hai chiesto. Ho cercato di spiegarne il funzionamento in questo post, su di un sito di cui sono l'howner, c'è anche il codice di una finestra di test e potrebbe mostrarTi altri tipi di approccio. Se mi dirai che ne pensi sarà gradito. Ciao P.S. : Per il Tuo virus non ne so niente, non uso windows dal secolo scorso Fatti non foste a viver come bruti... |
|
Scritto da Pietro Bruno Lancerotto |
2024-02-27 18:24:27 - Re: Utilizzo Socket
|
Cosa pensare ??
Eccezzionale !!! Ho fatto qualche adattamento Abbassato il bordo superiore perché la finestra andava sotto la Label "RICEZIONE" Poi leggendo l'ottimo post di cui sopra, ho messo il wrap = word Di conseguenza ho commentato le tre righe della scrolbar orizzontale Almeno quello che arriva si vede per intero senza doversi spostare in orizzontale E poi messo 100 nel numero di righe Poi, cosa che non c'entra nulla con Python, ho eliminato molti più caratteri L'intestazione con il FROM TO LEN a livello pratico delle nostre necessità non riveste alcuna importanza Poi leggendo le API consigliate dall'amico Andrej ho modificato il FROM con il Testo + chr(0) *10 e "tagliando" poi tutto a 10 caratteri In realtà il FROM ha i caratteri del nominativo ma potrebbe avere un -1 o altro in aggiunta per indicare se sei fisso, in movimento o altro Se il nominativo fosse 5 caratteri verrebbero aggiunti NUL nei "buchi" vuoti. Non sono 6 + 4 NULL ma bensi 10 con i NULL nelle posizioni mancanti Teniamo presente che il COSO è per i radioamatori Tornando a noi volevo chiederTi qualcosa sui ritorni a capo Ne file di LOG che io salvo ci sono per cui in quel text nel obs ci sono self.TESTO_RX.add_text(txt + '\n') in coda ho aggiunto pkt_gui_rcs_support.Salvataggio(txt + "\n") E' possibile che quella finestra Rispetti i ritorni a capo ?? Ovviamente sarà come scrivi nell'articolo che le righe impostate a 100 saranno in realtà di più Mi defisci collega, troppo onore. Mi reputo uno smanettone ignorante. Ciao e grazie ancora --
Bruno L. |
|
Scritto da Pietro Bruno Lancerotto |
2024-02-27 18:24:42 - Re: Utilizzo Socket
|
Cosa pensare ??
Eccezzionale !!! Ho fatto qualche adattamento Abbassato il bordo superiore perché la finestra andava sotto la Label "RICEZIONE" Poi leggendo l'ottimo post di cui sopra, ho messo il wrap = word Di conseguenza ho commentato le tre righe della scrolbar orizzontale Almeno quello che arriva si vede per intero senza doversi spostare in orizzontale E poi messo 100 nel numero di righe Poi, cosa che non c'entra nulla con Python, ho eliminato molti più caratteri L'intestazione con il FROM TO LEN a livello pratico delle nostre necessità non riveste alcuna importanza Poi leggendo le API consigliate dall'amico Andrej ho modificato il FROM con il Testo + chr(0) *10 e "tagliando" poi tutto a 10 caratteri In realtà il FROM ha i caratteri del nominativo ma potrebbe avere un -1 o altro in aggiunta per indicare se sei fisso, in movimento o altro Se il nominativo fosse 5 caratteri verrebbero aggiunti NUL nei "buchi" vuoti. Non sono 6 + 4 NULL ma bensi 10 con i NULL nelle posizioni mancanti Teniamo presente che il COSO è per i radioamatori Tornando a noi volevo chiederTi qualcosa sui ritorni a capo Ne file di LOG che io salvo ci sono per cui in quel text nel obs ci sono self.TESTO_RX.add_text(txt + '\n') in coda ho aggiunto pkt_gui_rcs_support.Salvataggio(txt + "\n") E' possibile che quella finestra Rispetti i ritorni a capo ?? Ovviamente sarà come scrivi nell'articolo che le righe impostate a 100 saranno in realtà di più Mi defisci collega, troppo onore. Mi reputo uno smanettone ignorante. Ciao e grazie ancora --
Bruno L. |
|
Scritto da Pietro Bruno Lancerotto |
2024-02-27 18:24:51 - Re: Utilizzo Socket
|
Cosa pensare ??
Eccezzionale !!! Ho fatto qualche adattamento Abbassato il bordo superiore perché la finestra andava sotto la Label "RICEZIONE" Poi leggendo l'ottimo post di cui sopra, ho messo il wrap = word Di conseguenza ho commentato le tre righe della scrolbar orizzontale Almeno quello che arriva si vede per intero senza doversi spostare in orizzontale E poi messo 100 nel numero di righe Poi, cosa che non c'entra nulla con Python, ho eliminato molti più caratteri L'intestazione con il FROM TO LEN a livello pratico delle nostre necessità non riveste alcuna importanza Poi leggendo le API consigliate dall'amico Andrej ho modificato il FROM con il Testo + chr(0) *10 e "tagliando" poi tutto a 10 caratteri In realtà il FROM ha i caratteri del nominativo ma potrebbe avere un -1 o altro in aggiunta per indicare se sei fisso, in movimento o altro Se il nominativo fosse 5 caratteri verrebbero aggiunti NUL nei "buchi" vuoti. Non sono 6 + 4 NULL ma bensi 10 con i NULL nelle posizioni mancanti Teniamo presente che il COSO è per i radioamatori Tornando a noi volevo chiederTi qualcosa sui ritorni a capo Ne file di LOG che io salvo ci sono per cui in quel text nel obs ci sono self.TESTO_RX.add_text(txt + '\n') in coda ho aggiunto pkt_gui_rcs_support.Salvataggio(txt + "\n") E' possibile che quella finestra Rispetti i ritorni a capo ?? Ovviamente sarà come scrivi nell'articolo che le righe impostate a 100 saranno in realtà di più Mi defisci collega, troppo onore. Mi reputo uno smanettone ignorante. Ciao e grazie ancora --
Bruno L. |
|
Scritto da nuzzopippo |
2024-02-28 10:34:30 - Re: Utilizzo Socket
|
In effetti e quello che si deve fare : capire le indicazioni, approfondire ed adattare il tutto ai propri scopi.
Si, ho provato le nuove impostazioni con il server che ho mandato ptima ... naturalmente, funzionano male con esso dato che trattano un protocollo di comunicazione che non vi è contemplato. ... C'è quel "nostre" che mi preoccupa un po' ... hai presente, vero, che quelle che Ti do solo solo indicazioni e che dovresti approfondire le tematiche rivenienti? Vi sono problematiche che temo potresti non aver presenti, che non danno molto fastidio a Te che codifichi ma se passi il Tuo lavoro ad altri è bene non ci siano ... Te ne indicherò un paio in seguito
La finestra rispetterà i ritorni a capo solo (e soltanto) se riceverà una stringa codificata quale utf-8, i singoli caratteri"\" e "n", passati come tali non verranno interpretati come new-line ... in pratica, dovresti decodificare l'insieme di bytes da passare alla finestra come 'utf-8'
Non credere io sia un "sapiente" sono a mia volta un (vecchio) smanettone ignorante che cerca di imparare qualcosa, magari su python ho avuto più tempo di Te ma rimani un collega Veniamo ora ai punti di cui Ti volevo avvertire : 1 - in utility.Delivery vi sono diverse istruzioni "raise RuntimeError ...." esse stanno li perché dovrebbero essere intercettate e gestite, altrimenti emetteranno un traceback in una eventuale shell di avvio, ovviamente quando lo ho manipolato non ho "gonfiato" il codice con la gestione degli errori, pensaci ... al minimo trasforma i "raise" in "return" 2 - più "pesante", il recv dei socket è bloccante, come è impostato al momento Chatterbox alla chiusura della applicazione rimane appeso un thread in attesa di comunicazione (è un daemon) ... non se ne accorge nessuno ma non è una bella cosa ... e qui si incappa in complessità da far piangere (socket + thread + strutturazione codice) ... soluzione di "emergenza" : A - in Chatterbox : - funzione "connect" definire un timeout per il socket immediatamente dopo la connessione, così: self.sok.connect((self.svr, self.port)) self.sok.settimeout(0.1)la "temporizzazione" è di un decimo di secondo - gestire l'errore di timeout nel target del thread, modificando il metodo "listen" come segue: def listen(self) -> None: while self.still: try: data = self.sok.recv(2048) if data: # qui andrebbe una queue per collezionare i dati giunti # ma complicherebbe le cose, mi limito a comunicare msg = ['RECEIVED', data[86:-3].decode(encoding="UTF-8", errors="ignore")] #print(msg) self.pub.send_message('LISTENERS', msg) except socket.timeout: continue self.sok.close() msg = ['OUTCOME', f'Connessione con {self.svr} chiusa'] self.pub.send_message('OBSERVER', msg) self.pub.unsubscribe('WORKER', self.obs)B - modificare PAGINA in modo che dia tempo alle operazioni del socket, ritengo sia bene spezzettare "_on_close" in modo da avere più "ordine" nella eliminazione delle registrazione e tempo, in questo modo: def _on_close(self) -> None: msg = ['CLOSING', 'CLOSING'] self.pub.send_message('WORKER', msg) self.top.after(500, self.__close) def __close(self) -> None: self.pub.unsubscribe('OBSERVER', self.obs) self.pub.unsubscribe('LISTENERS', self.obs) self.top.destroy()credo debba essere sufficiente. Comunque, thread e socket sono bestioline complicate ed approfondite, così come la strutturazione del codice ... hai ricevuto la mia email di risposta? Se ritieni posso inviarti una maccheronica traduzione (fatta da me e non pubblicabile) di un tutorial sui thread che ho trovato "buono" come spunto per approfondire l'argomento. Ciao Fatti non foste a viver come bruti... |
Pagina: Indietro 1 2 3 4 5 6 Avanti
Esegui il login per scrivere una risposta.