socket — módulo socket¶
Este módulo proporciona acceso a la interfaz de sockets BSD.
Diferencias con CPython
Por eficiencia y coherencia, los objetos socket en MicroPython implementan directamente una interfaz stream (similar a un fichero). En CPython, es necesario convertir un socket en un objeto similar a un fichero mediante el método makefile(). Este método sigue siendo compatible con MicroPython (pero no hace nada), por lo que, cuando importe la compatibilidad con CPython, asegúrate de usarlo.
Formato(s) de dirección de socket¶
El formato nativo de dirección de socket del módulo socket es un tipo de dato opaco devuelto por la función getaddrinfo(), que debe utilizarse para resolver direcciones textuales (incluidas las direcciones numéricas):
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)
Usar getaddrinfo() es la forma más eficiente (tanto en términos de memoria como de capacidad de procesamiento) y portable de trabajar con direcciones.
El módulo socket también proporciona una forma compatible con CPython de especificar direcciones mediante tuplas, como se describe a continuación. En la OpenMV Cam, el módulo socket está incorporado; las direcciones numéricas pueden indicarse directamente en formato de tupla, pero los nombres de dominio deben resolverse primero con getaddrinfo().
En resumen:
Usa siempre
getaddrinfo()para resolver nombres de host.Las direcciones de tupla descritas a continuación pueden usarse como atajo para direcciones numéricas, para soluciones rápidas y uso interactivo.
Formato de dirección de tupla para el módulo socket:
IPv4: (ipv4_address, port), donde ipv4_address es una cadena con una dirección IPv4 numérica en notación con puntos, p. ej.
"8.8.8.8", y port es un número de puerto entero en el rango 1-65535. Los nombres de dominio no se aceptan como ipv4_address; resuélvelos primero usandogetaddrinfo().IPv6: (ipv6_address, port, flowinfo, scopeid), donde ipv6_address es una cadena con una dirección IPv6 numérica en notación con dos puntos, p. ej.
"2001:db8::1", y port es un número de puerto entero en el rango 1-65535. flowinfo debe ser 0. scopeid es el identificador de ámbito de la interfaz para direcciones link-local. Los nombres de dominio no se aceptan como ipv6_address; resuélvelos primero usandogetaddrinfo().
Funciones¶
- socket.getaddrinfo(host: str, port: int, af: int = 0, type: int = 0, proto: int = 0, flags: int = 0, /) List[Tuple]¶
Traduce el argumento host/port a una secuencia de 5-tuplas que contienen todos los argumentos necesarios para crear un socket conectado a ese servicio. Los argumentos af, type y proto (que tienen el mismo significado que para la función
socket) pueden usarse para filtrar qué tipo de direcciones se devuelven. Si un parámetro no se especifica o es cero, pueden devolverse todas las combinaciones de direcciones (lo que requiere filtrado por parte del usuario).La lista resultante de 5-tuplas tiene la siguiente estructura:
(family, type, proto, canonname, sockaddr)El siguiente ejemplo muestra cómo conectarse a una url determinada:
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 recomendado de los parámetros de filtrado:
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])
Diferencias con CPython
CPython genera una excepción
socket.gaierror(subclase deOSError) en caso de error en esta función. MicroPython no tienesocket.gaierrory genera OSError directamente. Ten en cuenta que los números de error degetaddrinfo()forman un espacio de nombres independiente y pueden no coincidir con los números de error del móduloerrno. Para distinguir los errores degetaddrinfo(), se representan mediante números negativos, mientras que los errores estándar del sistema son números positivos (los números de error son accesibles mediante la propiedade.args[0]de un objeto de excepción). El uso de valores negativos es un detalle provisional que puede cambiar en el futuro.
Constantes¶
- socket.IPPROTO_IP: int¶
El nivel del protocolo IP. Se usa como argumento level en
setsockopt()junto con las opcionesIP_*.
- socket.IPPROTO_TCP: int¶
El protocolo TCP. No necesitas pasarlo a
socket(el tipo de socketSOCK_STREAMlo selecciona automáticamente); su único uso real es como argumento level ensetsockopt()junto con las opcionesTCP_*.
- socket.SOL_SOCKET: int¶
El nivel de opción del socket. Se usa como argumento level en
setsockopt()junto con las opcionesSO_*.
- socket.SO_REUSEADDR: int¶
Permite que el socket se vincule a una dirección/puerto que aún está en estado
TIME_WAIT.
- socket.SO_KEEPALIVE: int¶
Habilita la transmisión periódica de sondas de keep-alive en un socket conectado.
- socket.SO_SNDTIMEO: int¶
Tiempo de espera de envío, en milisegundos, pasado como argumento value a
setsockopt().
- socket.SO_RCVTIMEO: int¶
Tiempo de espera de recepción, en milisegundos, pasado como argumento value a
setsockopt().
- socket.IP_ADD_MEMBERSHIP: int¶
Une el socket a un grupo de multidifusión (multicast). Una opción de
setsockopt()a nivel deIPPROTO_IP.
- socket.IP_DROP_MEMBERSHIP: int¶
Abandona un grupo de multidifusión (multicast). Una opción de
setsockopt()a nivel deIPPROTO_IP.
- socket.TCP_NODELAY: int¶
Desactiva el algoritmo de Nagle. Una opción de
setsockopt()a nivel deIPPROTO_TCP.
- socket.MSG_PEEK: int¶
Para
recv()/recvfrom(): devuelve los datos sin eliminarlos de la cola de entrada.
- socket.MSG_DONTWAIT: int¶
Para
recv()/recvfrom(): realiza la operación en modo no bloqueante.
Clases¶
- class socket.socket(af: int = AF_INET, type: int = SOCK_STREAM, proto: int = IPPROTO_TCP, /)¶
Crea un nuevo socket usando la familia de direcciones, el tipo de socket y el número de protocolo dados. Especificar proto no es necesario en la mayoría de los casos (y no se recomienda); el argumento type selecciona automáticamente el protocolo necesario:
# Create STREAM TCP socket socket(AF_INET, SOCK_STREAM) # Create DGRAM UDP socket socket(AF_INET, SOCK_DGRAM)
- close() None¶
Marca el socket como cerrado y libera todos los recursos. Una vez que esto ocurre, todas las operaciones futuras sobre el objeto socket fallarán. El extremo remoto recibirá una indicación de EOF si el protocolo lo admite.
Los sockets se cierran automáticamente cuando son recolectados por el recolector de basura, pero se recomienda cerrarlos explícitamente con
close()tan pronto como hayas terminado de trabajar con ellos.
- listen(backlog: int = 2) None¶
Habilita a un servidor para aceptar conexiones. Si se especifica backlog, debe ser al menos 0 (si es menor, se establecerá en 0); y especifica el número de conexiones no aceptadas que el sistema permitirá antes de rechazar nuevas conexiones. Si no se especifica, se elige un valor predeterminado razonable.
- accept() Tuple['socket', Tuple]¶
Acepta una conexión. El socket debe estar vinculado a una dirección y a la escucha de conexiones. El valor de retorno es un par (conn, address) donde conn es un nuevo objeto socket utilizable para enviar y recibir datos en la conexión, y address es la dirección vinculada al socket en el otro extremo de la conexión.
- send(bytes: bytes) int¶
Envía datos al socket. El socket debe estar conectado a un socket remoto. Devuelve el número de bytes enviados, que puede ser menor que la longitud de los datos («escritura corta»).
- sendall(bytes: bytes) None¶
Envía todos los datos al socket. El socket debe estar conectado a un socket remoto. A diferencia de
send(), este método intentará enviar todos los datos, enviándolos por fragmentos de forma consecutiva.El comportamiento de este método en sockets no bloqueantes es indefinido. Por ello, en MicroPython se recomienda usar el método
write()en su lugar, que tiene la misma política de «sin escrituras cortas» para sockets bloqueantes, y devolverá el número de bytes enviados en sockets no bloqueantes.
- recv(bufsize: int, flags: int = 0) bytes¶
Recibe datos del socket. El valor de retorno es un objeto bytes que representa los datos recibidos. La cantidad máxima de datos que se recibirá de una vez se especifica con bufsize.
El argumento opcional flags es un OR a nivel de bits de banderas de mensaje (
MSG_PEEK,MSG_DONTWAIT), que tienen el mismo significado que en CPython.
- sendto(bytes: bytes, address: Any) int¶
Envía datos al socket. El socket no debe estar conectado a un socket remoto, ya que el socket de destino se especifica con address.
- recvfrom(bufsize: int, flags: int = 0) Tuple[bytes, Tuple]¶
Recibe datos del socket. El valor de retorno es un par (bytes, address) donde bytes es un objeto bytes que representa los datos recibidos y address es la dirección del socket que envía los datos.
Consulta la función
recv()para obtener una explicación del argumento opcional flags.
- setsockopt(level: int, optname: int, value: int | bytes) None¶
Establece el valor de la opción de socket dada. Las constantes simbólicas necesarias están definidas en el módulo socket (SO_*, etc.). El value puede ser un entero o un objeto similar a bytes que represente un búfer.
- settimeout(value: float | None) None¶
Establece un tiempo de espera en las operaciones de socket bloqueantes. El argumento value puede ser un número de punto flotante no negativo que exprese segundos, o None. Si se proporciona un valor distinto de cero, las operaciones de socket posteriores generarán una excepción
OSErrorsi el periodo de tiempo de espera ha transcurrido antes de que la operación se complete. Si se proporciona cero, el socket se pone en modo no bloqueante. Si se proporciona None, el socket se pone en modo bloqueante.Una alternativa portable y genérica es usar un objeto
select.poll. Esto permite esperar sobre varios objetos al mismo tiempo (y no solo sobre sockets, sino sobre objetos stream genéricos que admitan sondeo). Ejemplo:# 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
Diferencias con CPython
CPython genera una excepción
socket.timeouten caso de tiempo de espera, que es una subclase deOSError. MicroPython genera un OSError directamente en su lugar. Si usasexcept OSError:para capturar la excepción, tu código funcionará tanto en MicroPython como en CPython.
- setblocking(flag: bool) None¶
Establece el modo bloqueante o no bloqueante del socket: si flag es falso, el socket se establece en no bloqueante; en caso contrario, en modo bloqueante.
Este método es una forma abreviada de ciertas llamadas a
settimeout():sock.setblocking(True)equivale asock.settimeout(None)sock.setblocking(False)equivale asock.settimeout(0)
- makefile(mode: str = 'rb', buffering: int = 0, /) Any¶
Devuelve un objeto fichero asociado al socket. El tipo exacto devuelto depende de los argumentos dados a makefile(). El soporte se limita únicamente a los modos binarios (“rb”, “wb” y “rwb”). Los argumentos de CPython encoding, errors y newline no son compatibles.
Diferencias con CPython
Como MicroPython no admite flujos con búfer, el valor del parámetro buffering se ignora y se trata como si fuera 0 (sin búfer).
Diferencias con CPython
Cerrar el objeto fichero devuelto por makefile() TAMBIÉN cerrará el socket original.
- read(size: int | None = None) bytes¶
Lee hasta size bytes del socket. Devuelve un objeto bytes. Si no se proporciona size, lee todos los datos disponibles del socket hasta EOF; por tanto, el método no retornará hasta que el socket se cierre. Esta función intenta leer tantos datos como se solicitan (sin «lecturas cortas»). Sin embargo, esto puede no ser posible con un socket no bloqueante, en cuyo caso se devolverán menos datos.
- readinto(buf: bytearray | memoryview, nbytes: int | None = None) int¶
Lee bytes en buf. Si se especifica nbytes, lee como máximo esa cantidad de bytes. De lo contrario, lee como máximo len(buf) bytes. Al igual que
read(), este método sigue la política de «sin lecturas cortas».Valor de retorno: número de bytes leídos y almacenados en buf.
- readline() bytes¶
Lee una línea, que termina en un carácter de nueva línea.
Valor de retorno: la línea leída.
- write(buf: bytes) int¶
Escribe el búfer de bytes en el socket. Esta función intentará escribir todos los datos en un socket (sin «escrituras cortas»). Sin embargo, esto puede no ser posible con un socket no bloqueante, y el valor devuelto será menor que la longitud de buf.
Valor de retorno: número de bytes escritos.