View Full Version : [Python] Guida socket
agente mm8
04-04-2009, 15:44
Sapete dove posso trovare una buona guida ai socket in python? Quella sul sito non mi sembra tanto completa...
cdimauro
04-04-2009, 16:10
Con tutte le librerie che ha Python per internet, a te interessa veramente manipolare direttamente i socket?
A cosa ti servirebbero?
agente mm8
04-04-2009, 16:13
Quali altre possibilità ho?
cdimauro
04-04-2009, 16:34
Tantissime. Python ha una libreria molto ricca per accedere a internet.
Fai prima dirmi cosa ti serve (anche perché tra poco dovrei uscire :D). ;)
agente mm8
04-04-2009, 16:40
Dovrei semplicemente mettere in comunicazione più macchine e inviare e ricevere stringhe.
cdimauro
04-04-2009, 16:46
Se è solo per quello allora forse è meglio che usi i socket (http://docs.python.org/library/socket.html).
Nel link, verso la fine, trovi diversi esempi di semplici comunicazioni fra macchine.
Tantissime. Python ha una libreria molto ricca per accedere a internet.
Fai prima dirmi cosa ti serve (anche perché tra poco dovrei uscire :D). ;)
Approfitto della tua sapienza per chiederti: che libreria potrei usare in futuro per un semplice scambio di file? Tipo il computer A invia un file al computer B che sta "aspettando" il file, lo riceve e lo salva...
Credo anche in questo caso socket..
cdimauro
05-04-2009, 08:19
Lo penso anch'io, ma già per trasferire i file mi verrebbe in mente di utilizzare il protocollo FTP.
Comunque sono tante idee un po' eterogenee: è difficile dare una risposta che indirizzi verso una ben precisa direzione / libreria.
Ad esempio per quanto già scritto e soddisfare tutte le richieste si potrebbe pensare di mettere in piedi piccoli server HTTP, che in Python si tirano sù in pochi minuti. Ma potrebbe essere come sparare a una mosca con un cannone.
~FullSyst3m~
05-04-2009, 13:07
C'è il framework twisted che ha moltissimi strumenti per poter sfruttare il network.
Come libro invece consiglio Foundations of Python Network Programming. Trovi l'e-book con una semplice ricerca con BigG.
Ad esempio per quanto già scritto e soddisfare tutte le richieste si potrebbe pensare di mettere in piedi piccoli server HTTP, che in Python si tirano sù in pochi minuti. Ma potrebbe essere come sparare a una mosca con un cannone.
Usando le HTTPlib?
cdimauro
05-04-2009, 16:59
Io ho usato BasicSocketServer o qualcosa di simile.
~FullSyst3m~
05-04-2009, 17:12
Io ho usato BasicSocketServer o qualcosa di simile.
Mai sentito.
Sarei curioso di vedere questo server HHTP fatto in pochi minuti. Pensi di poter postare il codice quando hai un pò di tempo?
cdimauro
05-04-2009, 19:17
Non posso postare il codice, perché è roba aziendale. Alcuni spezzoni per rendere l'idea, sì:
InternetUtils.RunHTTPServer(Host, Port, MyHTTPRequestHandler)
Intanto ti dico che mi sono creato delle classi e funzioni che aiutano. RunHTTPServer è una funzione a cui passi l'IP e la porta da cui ricevere le richieste, e la classe da utilizzare per generare le apposite istanze per servirle, e lancia subito il server.
Un esempio di handler per gestire le richieste è il seguente:
class MyHTTPRequestHandler(InternetUtils.AdvancedHTTPRequestHandler):
server_version = 'MyHTTP/0.01alpha'
default_content_type = 'text/plain'
log_file = r'D:\tmp\MyHTTP.log'
def EncodeContent(self, message):
return message
def _list(self, Globals = None, Locals = None, Self = None, Inspect = None, **Parameters):
if Globals is not None:
Datas = globals()
elif locals is not None:
Datas = locals()
elif Self is not None:
Datas = self.__dict__
elif Inspect is not None:
Datas = dir(self)
else:
Key, Datas = '', {}
return self.send_message(str(sorted(Datas)))
def _get(self, Globals = None, Locals = None, Self = None, Inspect = None, **Parameters):
if Globals:
Key, Datas = Globals, globals()
elif Locals:
Key, Datas = Locals, locals()
elif Self:
Key, Datas = Self, self.__dict__
else:
Key, Datas = '', {}
return self.send_message(str(Datas[Key]) if Key in Datas else 'ERROR! Data not found!!!')
AdvancedHTTPRequestHandler è la classe madre che ho creato per gestire parecchi aspetti delle richieste in modo automatico. Praticamente fa tutto lei. :D
Io devo definire soltanto le seguenti cose:
la versione del server;
il MIMEType del contenuto che eroga (ovviamente per singole precise richieste si può cambiare);
Un file di log in cui riportare tutte le richieste arrivate (tipo il log di apache; ovviamente è opzionale).
Il metodo EncodeContent esegue eventuali codifiche. In questo caso i dati restituiti sono testo "nudo e crudo", per cui semplicemente restituisce ciò che riceve.
Fatto questo è sufficiente definire dei metodi che verranno automaticamente chiamati quando arriva una richiesta che li reclama. Qui ne sono definiti due, _list e _get.
Il nome sembra strano con quegli underscore all'inizio, ma ciò è necessario perché quando la classe madre effettua il parsing dell'URI che è arrivata, sostuisce tutti gli / in _ in modo da poter mappare correttamente l'URI a un preciso metodo della classe.
Quindi se tu richiami il server con questa URI:
http://192.168.0.1/list?Globals=Yes
verrà richiamato il metodo _list col parametro Globals valorizzato con la stringa 'Yes'.
Qualunque richiesta per cui non esiste un metodo mappato viene dirottata nel metodo standard _bad, che provvede a visualizzare un messaggio d'errore standard.
~FullSyst3m~
05-04-2009, 19:52
Non posso postare il codice, perché è roba aziendale. Alcuni spezzoni per rendere l'idea, sì:
InternetUtils.RunHTTPServer(Host, Port, MyHTTPRequestHandler)
Ovviamente non volevo il codice aziendale, ma un esempio ;)
Intanto ti dico che mi sono creato delle classi e funzioni che aiutano.
Come fai sempre del resto :)
RunHTTPServer è una funzione a cui passi l'IP e la porta da cui ricevere le richieste, e la classe da utilizzare per generare le apposite istanze per servirle, e lancia subito il server.
Interessante.
Un esempio di handler per gestire le richieste è il seguente:
class MyHTTPRequestHandler(InternetUtils.AdvancedHTTPRequestHandler):
server_version = 'MyHTTP/0.01alpha'
default_content_type = 'text/plain'
log_file = r'D:\tmp\MyHTTP.log'
def EncodeContent(self, message):
return message
def _list(self, Globals = None, Locals = None, Self = None, Inspect = None, **Parameters):
if Globals is not None:
Datas = globals()
elif locals is not None:
Datas = locals()
elif Self is not None:
Datas = self.__dict__
elif Inspect is not None:
Datas = dir(self) #qua cosa mostri?
else:
Key, Datas = '', {}
return self.send_message(str(sorted(Datas))) #dove è send_message? In qualche altra parte di codice?
def _get(self, Globals = None, Locals = None, Self = None, Inspect = None, **Parameters):
if Globals:
Key, Datas = Globals, globals() #questa funzione cosa fa?
elif Locals:
Key, Datas = Locals, locals() #come sopra
elif Self:
Key, Datas = Self, self.__dict__ #dove lo prende questo dizionario?
else:
Key, Datas = '', {}
return self.send_message(str(Datas[Key]) if Key in Datas else 'ERROR! Data not found!!!')
AdvancedHTTPRequestHandler è la classe madre che ho creato per gestire parecchi aspetti delle richieste in modo automatico. Praticamente fa tutto lei. :D
Ti segno in grassetto quello che non mi è chiaro e aggiungo commento al codice. Comunque stai usando BasicSocketServer in questo codice?
In pratica aggiungi funzionalità alla classe dalla quale erediti.
Il metodo EncodeContent esegue eventuali codifiche. In questo caso i dati restituiti sono testo "nudo e crudo", per cui semplicemente restituisce ciò che riceve.
Non fai un controllo sull'input?
Fatto questo è sufficiente definire dei metodi che verranno automaticamente chiamati quando arriva una richiesta che li reclama. Qui ne sono definiti due, _list e _get.
Il nome sembra strano con quegli underscore all'inizio, ma ciò è necessario perché quando la classe madre effettua il parsing dell'URI che è arrivata, sostuisce tutti gli / in _ in modo da poter mappare correttamente l'URI a un preciso metodo della classe.
Quindi se tu richiami il server con questa URI:
http://192.168.0.1/list?Globals=Yes
verrà richiamato il metodo _list col parametro Globals valorizzato con la stringa 'Yes'.
Qualunque richiesta per cui non esiste un metodo mappato viene dirottata nel metodo standard _bad, che provvede a visualizzare un messaggio d'errore standard.
Io sto leggendo adesso quel libro riguardo la programmazione di rete con Python, ma mi chiedo: questo server HTTP cosa contiene? Cioè, come faccio io ad inserire ad esempio un sito su questo server e a renderlo raggiungibile? E richiama in automatico la tua classe quando inseriso un URL nel browser?
P.S: in quel link di esempio che hai scritto si è vista la valorizzazione del parametro Global, ma gli altri parametri in un URL come si potrebbero presentare? Con il semplice nome della variabile come Globals = Yes in questo caso?
P.S2: ma quel _ prima del nome di un metodo o variabile non vuol dire che la rende privata?
cdimauro
06-04-2009, 14:05
Ti segno in grassetto quello che non mi è chiaro e aggiungo commento al codice.
Di seguito tutte le tue risposte alle domande contenute nel sorgente.
Datas = dir(self) #qua cosa mostri?
Faccio introspezione sull'oggetto stesso, e recupero tutti i membri (variabili e metodi) esso contenuti.
return self.send_message(str(sorted(Datas))) #dove è send_message? In qualche altra parte di codice?
Si trova nella classe madre che gestisce le richieste HTTP, AdvancedHTTPRequestHandler.
Key, Datas = Globals, globals() #questa funzione cosa fa?
globals() ritorna un dizionario con l'elenco di tutte le variabili globali.
Key, Datas = Locals, locals() #come sopra
globals() ritorna un dizionario con l'elenco di tutte le variabili locali.
Key, Datas = Self, self.__dict__ #dove lo prende questo dizionario?
Ogni oggetto Python "non banale / standard" ha al suo interno un dizionario in cui sono riportate le variabili e i metodi d'istanza.
In pratica tutte queste informazioni mi servono per controllare dall'esterno lo stato del server. :D
Comunque stai usando BasicSocketServer in questo codice?
No, sto usando SocketServer.ThreadingTCPServer per il server TCP, e BaseHTTPServer.BaseHTTPRequestHandler per gestire le richeste HTTP.
In pratica aggiungi funzionalità alla classe dalla quale erediti.
Sì.
Non fai un controllo sull'input?
Non ne ho bisogno, ma potrei farlo.
Io sto leggendo adesso quel libro riguardo la programmazione di rete con Python, ma mi chiedo: questo server HTTP cosa contiene? Cioè, come faccio io ad inserire ad esempio un sito su questo server e a renderlo raggiungibile?
Semplice: ti basta lanciare quello script e il server è già pronto e funzionante.
Supponendo che il codice l'abbia salvato su un file che si chiama server.py, basta
python server.py
e ho già il server attivo e pronto a servire le richieste che arriveranno.
E richiama in automatico la tua classe quando inseriso un URL nel browser?
Sì.
P.S: in quel link di esempio che hai scritto si è vista la valorizzazione del parametro Global, ma gli altri parametri in un URL come si potrebbero presentare? Con il semplice nome della variabile come Globals = Yes in questo caso?
Sì, e se ci sono più parametri è sufficiente separarli con la e commerciale (&):
http://192.168.0.1/list?Globals=Yes&Locals=Yes
P.S2: ma quel _ prima del nome di un metodo o variabile non vuol dire che la rende privata?
No. Rappresenta la root dell'URI. /get -> _get ;)
~FullSyst3m~
06-04-2009, 14:25
Di seguito tutte le tue risposte alle domande contenute nel sorgente.
Datas = dir(self) #qua cosa mostri?
Faccio introspezione sull'oggetto stesso, e recupero tutti i membri (variabili e metodi) esso contenuti.
return self.send_message(str(sorted(Datas))) #dove è send_message? In qualche altra parte di codice?
Si trova nella classe madre che gestisce le richieste HTTP, AdvancedHTTPRequestHandler.
Key, Datas = Globals, globals() #questa funzione cosa fa?
globals() ritorna un dizionario con l'elenco di tutte le variabili globali.
Key, Datas = Locals, locals() #come sopra
globals() ritorna un dizionario con l'elenco di tutte le variabili locali.
Key, Datas = Self, self.__dict__ #dove lo prende questo dizionario?
Ogni oggetto Python "non banale / standard" ha al suo interno un dizionario in cui sono riportate le variabili e i metodi d'istanza.
In pratica tutte queste informazioni mi servono per controllare dall'esterno lo stato del server. :D
No, sto usando SocketServer.ThreadingTCPServer per il server TCP, e BaseHTTPServer.BaseHTTPRequestHandler per gestire le richeste HTTP.
Sì.
Non ne ho bisogno, ma potrei farlo.
Semplice: ti basta lanciare quello script e il server è già pronto e funzionante.
Supponendo che il codice l'abbia salvato su un file che si chiama server.py, basta
python server.py
e ho già il server attivo e pronto a servire le richieste che arriveranno.
Sì.
Sì, e se ci sono più parametri è sufficiente separarli con la e commerciale (&):
http://192.168.0.1/list?Globals=Yes&Locals=Yes
No. Rappresenta la root dell'URI. /get -> _get ;)
In teoria è chiaro, tranne la prima parte che non l'ho inquadrata bene non avendo mai fatto prove.
Riguardo il _ serve anche a rendere privata una funzione o variabile. O no?
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.