socket — modulo socket¶
Questo modulo fornisce l’accesso all’interfaccia socket BSD.
Differenze rispetto a CPython
Per efficienza e coerenza, gli oggetti socket in MicroPython implementano direttamente un’interfaccia stream (file-like). In CPython, è necessario convertire un socket in un oggetto file-like usando il metodo makefile(). Questo metodo è ancora supportato da MicroPython (ma è un’operazione nulla), quindi quando la compatibilità con CPython è importante, assicurati di usarlo.
Formato/i degli indirizzi socket¶
Il formato nativo degli indirizzi socket del modulo socket è un tipo di dato opaco restituito dalla funzione getaddrinfo(), che deve essere usata per risolvere un indirizzo testuale (inclusi gli indirizzi numerici):
sockaddr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# You must use getaddrinfo() even for numeric addresses
sockaddr = socket.getaddrinfo('127.0.0.1', 80)[0][-1]
# Now you can use that address
sock.connect(sockaddr)
L’uso di getaddrinfo() è il modo più efficiente (sia in termini di memoria che di potenza di elaborazione) e portabile per lavorare con gli indirizzi.
Il modulo socket fornisce anche un modo compatibile con CPython per specificare gli indirizzi usando tuple, come descritto di seguito. Sulla OpenMV Cam il modulo socket è integrato; gli indirizzi numerici possono essere forniti direttamente nel formato a tupla, ma i nomi di dominio devono prima essere risolti con getaddrinfo().
Riassumendo:
Usa sempre
getaddrinfo()per risolvere i nomi host.Gli indirizzi a tupla descritti di seguito possono essere usati come scorciatoia per gli indirizzi numerici, per prove rapide e l’uso interattivo.
Formato degli indirizzi a tupla per il modulo socket:
IPv4: (ipv4_address, port), dove ipv4_address è una stringa con un indirizzo IPv4 numerico in notazione puntata, ad esempio
"8.8.8.8", e port è un numero di porta intero nell’intervallo 1-65535. I nomi di dominio non sono accettati come ipv4_address; risolvili prima usandogetaddrinfo().IPv6: (ipv6_address, port, flowinfo, scopeid), dove ipv6_address è una stringa con un indirizzo IPv6 numerico in notazione con due punti, ad esempio
"2001:db8::1", e port è un numero di porta intero nell’intervallo 1-65535. flowinfo deve essere 0. scopeid è l’identificatore dello scope dell’interfaccia per gli indirizzi link-local. I nomi di dominio non sono accettati come ipv6_address; risolvili prima usandogetaddrinfo().
Funzioni¶
- socket.getaddrinfo(host: str, port: int, af: int = 0, type: int = 0, proto: int = 0, flags: int = 0, /) List[Tuple]¶
Traduce l’argomento host/port in una sequenza di tuple di 5 elementi che contengono tutti gli argomenti necessari per creare un socket connesso a quel servizio. Gli argomenti af, type e proto (che hanno lo stesso significato che hanno per la funzione
socket) possono essere usati per filtrare quale tipo di indirizzi viene restituito. Se un parametro non è specificato o è zero, possono essere restituite tutte le combinazioni di indirizzi (richiedendo un filtraggio lato utente).L’elenco risultante di tuple di 5 elementi ha la seguente struttura:
(family, type, proto, canonname, sockaddr)L’esempio seguente mostra come connettersi a un dato url:
s = socket.socket() # This assumes that if "type" is not specified, an address for # SOCK_STREAM will be returned, which may be not true s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1])
Uso consigliato dei parametri di filtraggio:
s = socket.socket() # Guaranteed to return an address which can be connect'ed to for # stream operation. s.connect(socket.getaddrinfo('www.micropython.org', 80, 0, SOCK_STREAM)[0][-1])
Differenze rispetto a CPython
CPython solleva un’eccezione
socket.gaierror(sottoclasse diOSError) in caso di errore in questa funzione. MicroPython non hasocket.gaierrore solleva direttamente OSError. Si noti che i numeri di errore digetaddrinfo()formano un namespace separato e potrebbero non corrispondere ai numeri di errore del moduloerrno. Per distinguere gli errori digetaddrinfo(), essi sono rappresentati da numeri negativi, mentre gli errori di sistema standard sono numeri positivi (i numeri di errore sono accessibili usando la proprietàe.args[0]da un oggetto eccezione). L’uso di valori negativi è un dettaglio provvisorio che potrebbe cambiare in futuro.
Costanti¶
- socket.IPPROTO_IP: int¶
Il livello del protocollo IP. Usato come argomento level di
setsockopt()insieme alle opzioniIP_*.
- socket.IPPROTO_TCP: int¶
Il protocollo TCP. Non è necessario passarlo a
socket(il tipo di socketSOCK_STREAMlo seleziona automaticamente); il suo unico utilizzo reale è come argomento level disetsockopt()insieme alle opzioniTCP_*.
- socket.SOL_SOCKET: int¶
Il livello delle opzioni del socket. Usato come argomento level di
setsockopt()insieme alle opzioniSO_*.
- socket.SO_REUSEADDR: int¶
Consente al socket di effettuare il bind a un indirizzo/porta che si trova ancora nello stato
TIME_WAIT.
- socket.SO_KEEPALIVE: int¶
Abilita la trasmissione periodica di sonde keep-alive su un socket connesso.
- socket.SO_SNDTIMEO: int¶
Timeout di invio, in millisecondi, passato come argomento value a
setsockopt().
- socket.SO_RCVTIMEO: int¶
Timeout di ricezione, in millisecondi, passato come argomento value a
setsockopt().
- socket.IP_ADD_MEMBERSHIP: int¶
Si unisce a un gruppo multicast. Un’opzione di
setsockopt()a livelloIPPROTO_IP.
- socket.IP_DROP_MEMBERSHIP: int¶
Abbandona un gruppo multicast. Un’opzione di
setsockopt()a livelloIPPROTO_IP.
- socket.TCP_NODELAY: int¶
Disabilita l’algoritmo di Nagle. Un’opzione di
setsockopt()a livelloIPPROTO_TCP.
- socket.MSG_PEEK: int¶
Per
recv()/recvfrom(): restituisce i dati senza rimuoverli dalla coda di input.
- socket.MSG_DONTWAIT: int¶
Per
recv()/recvfrom(): esegue l’operazione in modalità non bloccante.
Classi¶
- class socket.socket(af: int = AF_INET, type: int = SOCK_STREAM, proto: int = IPPROTO_TCP, /)¶
Crea un nuovo socket usando la famiglia di indirizzi, il tipo di socket e il numero di protocollo indicati. Specificare proto nella maggior parte dei casi non è necessario (e non è consigliato); l’argomento type seleziona automaticamente il protocollo necessario:
# Create STREAM TCP socket socket(AF_INET, SOCK_STREAM) # Create DGRAM UDP socket socket(AF_INET, SOCK_DGRAM)
- close() None¶
Contrassegna il socket come chiuso e rilascia tutte le risorse. Una volta che ciò avviene, tutte le operazioni future sull’oggetto socket falliranno. L’estremità remota riceverà un’indicazione EOF se supportata dal protocollo.
I socket vengono chiusi automaticamente quando vengono raccolti dal garbage collector, ma è consigliabile chiuderli esplicitamente con
close()non appena hai finito di lavorare con essi.
- bind(address: Any) None¶
Effettua il bind del socket a address. Il socket non deve essere già sottoposto a bind.
- listen(backlog: int = 2) None¶
Consente a un server di accettare connessioni. Se backlog è specificato, deve essere almeno 0 (se è inferiore, verrà impostato a 0); e specifica il numero di connessioni non accettate che il sistema consentirà prima di rifiutare nuove connessioni. Se non specificato, viene scelto un valore predefinito ragionevole.
- accept() Tuple['socket', Tuple]¶
Accetta una connessione. Il socket deve essere sottoposto a bind a un indirizzo e in ascolto di connessioni. Il valore di ritorno è una coppia (conn, address) dove conn è un nuovo oggetto socket utilizzabile per inviare e ricevere dati sulla connessione, e address è l’indirizzo associato al socket all’altra estremità della connessione.
- send(bytes: bytes) int¶
Invia dati al socket. Il socket deve essere connesso a un socket remoto. Restituisce il numero di byte inviati, che può essere inferiore alla lunghezza dei dati («short write»).
- sendall(bytes: bytes) None¶
Invia tutti i dati al socket. Il socket deve essere connesso a un socket remoto. A differenza di
send(), questo metodo tenterà di inviare tutti i dati, inviandoli un blocco alla volta in modo consecutivo.Il comportamento di questo metodo sui socket non bloccanti non è definito. Per questo motivo, in MicroPython, è consigliabile usare invece il metodo
write(), che ha la stessa politica di «nessuna short write» per i socket bloccanti e restituirà il numero di byte inviati sui socket non bloccanti.
- recv(bufsize: int, flags: int = 0) bytes¶
Riceve dati dal socket. Il valore di ritorno è un oggetto bytes che rappresenta i dati ricevuti. La quantità massima di dati da ricevere in una sola volta è specificata da bufsize.
L’argomento opzionale flags è un OR bit a bit di flag di messaggio (
MSG_PEEK,MSG_DONTWAIT), che hanno lo stesso significato che hanno in CPython.
- sendto(bytes: bytes, address: Any) int¶
Invia dati al socket. Il socket non deve essere connesso a un socket remoto, poiché il socket di destinazione è specificato da address.
- recvfrom(bufsize: int, flags: int = 0) Tuple[bytes, Tuple]¶
Riceve dati dal socket. Il valore di ritorno è una coppia (bytes, address) dove bytes è un oggetto bytes che rappresenta i dati ricevuti e address è l’indirizzo del socket che invia i dati.
Vedi la funzione
recv()per una spiegazione dell’argomento opzionale flags.
- setsockopt(level: int, optname: int, value: int | bytes) None¶
Imposta il valore dell’opzione del socket indicata. Le costanti simboliche necessarie sono definite nel modulo socket (SO_* ecc.). Il value può essere un intero o un oggetto bytes-like che rappresenta un buffer.
- settimeout(value: float | None) None¶
Imposta un timeout sulle operazioni del socket bloccanti. L’argomento value può essere un numero in virgola mobile non negativo che esprime secondi, oppure None. Se viene fornito un valore diverso da zero, le successive operazioni sul socket solleveranno un’eccezione
OSErrorse il periodo di timeout è trascorso prima che l’operazione sia completata. Se viene fornito zero, il socket viene messo in modalità non bloccante. Se viene fornito None, il socket viene messo in modalità bloccante.Un’alternativa portabile e generica è usare un oggetto
select.poll. Questo consente di attendere su più oggetti contemporaneamente (e non solo su socket, ma su generici oggetti stream che supportano il polling). Esempio:# Instead of: s.settimeout(1.0) # time in seconds s.read(10) # may timeout # Use: poller = select.poll() poller.register(s, select.POLLIN) res = poller.poll(1000) # time in milliseconds if not res: # s is still not ready for input, i.e. operation timed out
Differenze rispetto a CPython
CPython solleva un’eccezione
socket.timeoutin caso di timeout, che è una sottoclasse diOSError. MicroPython solleva invece direttamente un OSError. Se usiexcept OSError:per catturare l’eccezione, il tuo codice funzionerà sia in MicroPython che in CPython.
- setblocking(flag: bool) None¶
Imposta la modalità bloccante o non bloccante del socket: se flag è falso, il socket viene impostato come non bloccante, altrimenti come bloccante.
Questo metodo è una scorciatoia per determinate chiamate a
settimeout():sock.setblocking(True)equivale asock.settimeout(None)sock.setblocking(False)equivale asock.settimeout(0)
- makefile(mode: str = 'rb', buffering: int = 0, /) Any¶
Restituisce un oggetto file associato al socket. Il tipo esatto restituito dipende dagli argomenti forniti a makefile(). Il supporto è limitato alle sole modalità binarie (“rb”, “wb” e “rwb”). Gli argomenti di CPython encoding, errors e newline non sono supportati.
Differenze rispetto a CPython
Poiché MicroPython non supporta gli stream con buffer, il valore del parametro buffering viene ignorato e trattato come se fosse 0 (senza buffer).
Differenze rispetto a CPython
La chiusura dell’oggetto file restituito da makefile() chiuderà ANCHE il socket originale.
- read(size: int | None = None) bytes¶
Legge fino a size byte dal socket. Restituisce un oggetto bytes. Se size non è fornito, legge tutti i dati disponibili dal socket fino all’EOF; pertanto il metodo non ritornerà finché il socket non viene chiuso. Questa funzione tenta di leggere tutti i dati richiesti (nessuna «short read»). Tuttavia ciò potrebbe non essere possibile con un socket non bloccante, e in tal caso verranno restituiti meno dati.
- readinto(buf: bytearray | memoryview, nbytes: int | None = None) int¶
Legge byte in buf. Se nbytes è specificato, legge al massimo quel numero di byte. Altrimenti, legge al massimo len(buf) byte. Proprio come
read(), questo metodo segue la politica di «nessuna short read».Valore di ritorno: numero di byte letti e memorizzati in buf.
- readline() bytes¶
Legge una riga, terminata da un carattere di nuova riga.
Valore di ritorno: la riga letta.
- write(buf: bytes) int¶
Scrive il buffer di byte nel socket. Questa funzione tenterà di scrivere tutti i dati su un socket (nessuna «short write»). Tuttavia ciò potrebbe non essere possibile con un socket non bloccante, e il valore restituito sarà inferiore alla lunghezza di buf.
Valore di ritorno: numero di byte scritti.