socket — módulo socket

Este módulo fornece acesso à interface de sockets BSD.

Diferença em relação ao CPython

Por eficiência e consistência, os objetos socket no MicroPython implementam diretamente uma interface stream (semelhante a arquivo). No CPython, é necessário converter um socket em um objeto semelhante a arquivo usando o método makefile(). Esse método ainda é suportado pelo MicroPython (mas é uma no-op), portanto, onde a compatibilidade com o CPython importar, certifique-se de usá-lo.

Formato(s) de endereço de socket

O formato de endereço de socket nativo do módulo socket é um tipo de dado opaco retornado pela função getaddrinfo(), que deve ser usado para resolver endereços textuais (incluindo endereços numéricos):

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() é a forma mais eficiente (tanto em termos de memória quanto de poder de processamento) e portável de trabalhar com endereços.

O módulo socket também fornece uma maneira compatível com o CPython de especificar endereços usando tuplas, conforme descrito abaixo. Na OpenMV Cam, o módulo socket é integrado; endereços numéricos podem ser fornecidos diretamente no formato de tupla, mas nomes de domínio devem primeiro ser resolvidos com getaddrinfo().

Resumindo:

  • Sempre use getaddrinfo() para resolver nomes de host.

  • Os endereços em tupla descritos abaixo podem ser usados como atalho para endereços numéricos, para soluções rápidas e uso interativo.

Formato de endereço em tupla para o módulo socket:

  • IPv4: (ipv4_address, port), onde ipv4_address é uma string com endereço IPv4 numérico em notação de pontos, por exemplo "8.8.8.8", e port é um número de porta inteiro no intervalo 1-65535. Nomes de domínio não são aceitos como ipv4_address; resolva-os primeiro usando getaddrinfo().

  • IPv6: (ipv6_address, port, flowinfo, scopeid), onde ipv6_address é uma string com endereço IPv6 numérico em notação de dois-pontos, por exemplo "2001:db8::1", e port é um número de porta inteiro no intervalo 1-65535. flowinfo deve ser 0. scopeid é o identificador de escopo de interface para endereços link-local. Nomes de domínio não são aceitos como ipv6_address; resolva-os primeiro usando getaddrinfo().

Funções

socket.getaddrinfo(host: str, port: int, af: int = 0, type: int = 0, proto: int = 0, flags: int = 0, /) List[Tuple]

Traduz o argumento host/port em uma sequência de 5-tuplas que contêm todos os argumentos necessários para criar um socket conectado a esse serviço. Os argumentos af, type e proto (que têm o mesmo significado que na função socket) podem ser usados para filtrar quais tipos de endereços são retornados. Se um parâmetro não for especificado ou for zero, todas as combinações de endereços podem ser retornadas (exigindo filtragem por parte do usuário).

A lista resultante de 5-tuplas tem a seguinte estrutura:

(family, type, proto, canonname, sockaddr)

O exemplo a seguir mostra como conectar a uma 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 dos parâmetros de filtragem:

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])

Diferença em relação ao CPython

O CPython levanta uma exceção socket.gaierror (subclasse de OSError) em caso de erro nesta função. O MicroPython não possui socket.gaierror e levanta OSError diretamente. Observe que os números de erro de getaddrinfo() formam um namespace separado e podem não coincidir com os números de erro do módulo errno. Para distinguir os erros de getaddrinfo(), eles são representados por números negativos, enquanto os erros padrão do sistema são números positivos (os números de erro são acessíveis usando a propriedade e.args[0] de um objeto de exceção). O uso de valores negativos é um detalhe provisório que pode mudar no futuro.

socket.inet_ntop(af: int, bin_addr: bytes) str

Converte um endereço de rede binário bin_addr da família de endereços af fornecida em uma representação textual:

>>> socket.inet_ntop(socket.AF_INET, b"\x7f\0\0\1")
'127.0.0.1'
socket.inet_pton(af: int, txt_addr: str) bytes

Converte um endereço de rede textual txt_addr da família de endereços af fornecida em uma representação binária:

>>> socket.inet_pton(socket.AF_INET, "1.2.3.4")
b'\x01\x02\x03\x04'

Constantes

socket.AF_INET: int

Família de endereços IPv4.

socket.AF_INET6: int

Família de endereços IPv6.

socket.SOCK_STREAM: int

Tipo de socket de stream (TCP).

socket.SOCK_DGRAM: int

Tipo de socket de datagrama (UDP).

socket.SOCK_RAW: int

Tipo de socket raw.

socket.IPPROTO_IP: int

O nível do protocolo IP. Usado como argumento level para setsockopt() juntamente com as opções IP_*.

socket.IPPROTO_TCP: int

O protocolo TCP. Você não precisa passá-lo para socket (o tipo de socket SOCK_STREAM o seleciona automaticamente); seu único uso real é como argumento level para setsockopt() juntamente com as opções TCP_*.

socket.SOL_SOCKET: int

O nível de opção de socket. Usado como argumento level para setsockopt() juntamente com as opções SO_*.

socket.SO_REUSEADDR: int

Permite que o socket faça bind a um endereço/porta que ainda esteja no estado TIME_WAIT.

socket.SO_BROADCAST: int

Permite o envio de datagramas para um endereço de broadcast.

socket.SO_KEEPALIVE: int

Habilita a transmissão periódica de sondas keep-alive em um socket conectado.

socket.SO_SNDTIMEO: int

Timeout de envio, em milissegundos, passado como argumento value para setsockopt().

socket.SO_RCVTIMEO: int

Timeout de recebimento, em milissegundos, passado como argumento value para setsockopt().

socket.IP_ADD_MEMBERSHIP: int

Entra em um grupo multicast. Uma opção de setsockopt() de nível IPPROTO_IP.

socket.IP_DROP_MEMBERSHIP: int

Sai de um grupo multicast. Uma opção de setsockopt() de nível IPPROTO_IP.

socket.TCP_NODELAY: int

Desabilita o algoritmo de Nagle. Uma opção de setsockopt() de nível IPPROTO_TCP.

socket.MSG_PEEK: int

Para recv() / recvfrom(): retorna os dados sem removê-los da fila de entrada.

socket.MSG_DONTWAIT: int

Para recv() / recvfrom(): executa a operação em modo não bloqueante.

Classes

class socket.socket(af: int = AF_INET, type: int = SOCK_STREAM, proto: int = IPPROTO_TCP, /)

Cria um novo socket usando a família de endereços, o tipo de socket e o número de protocolo fornecidos. Especificar proto na maioria dos casos não é necessário (e não é recomendado); o argumento type seleciona o protocolo necessário automaticamente:

# Create STREAM TCP socket
socket(AF_INET, SOCK_STREAM)
# Create DGRAM UDP socket
socket(AF_INET, SOCK_DGRAM)
close() None

Marca o socket como fechado e libera todos os recursos. Uma vez que isso aconteça, todas as operações futuras no objeto socket falharão. A extremidade remota receberá uma indicação de EOF, se suportada pelo protocolo.

Os sockets são fechados automaticamente quando são coletados pelo garbage collector, mas é recomendável fechá-los explicitamente com close() assim que você terminar de trabalhar com eles.

bind(address: Any) None

Faz o bind do socket a address. O socket não deve estar previamente vinculado.

listen(backlog: int = 2) None

Permite que um servidor aceite conexões. Se backlog for especificado, deve ser pelo menos 0 (se for menor, será definido como 0); e especifica o número de conexões não aceitas que o sistema permitirá antes de recusar novas conexões. Se não for especificado, um valor padrão razoável é escolhido.

accept() Tuple['socket', Tuple]

Aceita uma conexão. O socket deve estar vinculado a um endereço e ouvindo por conexões. O valor de retorno é um par (conn, address) onde conn é um novo objeto socket utilizável para enviar e receber dados na conexão, e address é o endereço vinculado ao socket na outra extremidade da conexão.

connect(address: Any) None

Conecta a um socket remoto em address.

send(bytes: bytes) int

Envia dados para o socket. O socket deve estar conectado a um socket remoto. Retorna o número de bytes enviados, que pode ser menor que o comprimento dos dados (“short write”).

sendall(bytes: bytes) None

Envia todos os dados para o socket. O socket deve estar conectado a um socket remoto. Ao contrário de send(), este método tentará enviar todos os dados, enviando-os bloco a bloco consecutivamente.

O comportamento deste método em sockets não bloqueantes é indefinido. Por isso, no MicroPython, recomenda-se usar o método write(), que tem a mesma política de “sem short writes” para sockets bloqueantes e retornará o número de bytes enviados em sockets não bloqueantes.

recv(bufsize: int, flags: int = 0) bytes

Recebe dados do socket. O valor de retorno é um objeto bytes representando os dados recebidos. A quantidade máxima de dados a ser recebida de uma vez é especificada por bufsize.

O argumento opcional flags é um OR bit a bit de flags de mensagem (MSG_PEEK, MSG_DONTWAIT), que têm o mesmo significado que no CPython.

sendto(bytes: bytes, address: Any) int

Envia dados para o socket. O socket não deve estar conectado a um socket remoto, já que o socket de destino é especificado por address.

recvfrom(bufsize: int, flags: int = 0) Tuple[bytes, Tuple]

Recebe dados do socket. O valor de retorno é um par (bytes, address) onde bytes é um objeto bytes representando os dados recebidos e address é o endereço do socket que enviou os dados.

Consulte a função recv() para uma explicação do argumento opcional flags.

setsockopt(level: int, optname: int, value: int | bytes) None

Define o valor da opção de socket fornecida. As constantes simbólicas necessárias são definidas no módulo socket (SO_* etc.). O value pode ser um inteiro ou um objeto semelhante a bytes representando um buffer.

settimeout(value: float | None) None

Define um timeout em operações de socket bloqueantes. O argumento value pode ser um número de ponto flutuante não negativo expressando segundos, ou None. Se um valor diferente de zero for fornecido, as operações de socket subsequentes levantarão uma exceção OSError se o período do timeout tiver decorrido antes de a operação ser concluída. Se zero for fornecido, o socket é colocado em modo não bloqueante. Se None for fornecido, o socket é colocado em modo bloqueante.

Uma alternativa portável e genérica é usar um objeto select.poll. Isso permite aguardar em múltiplos objetos ao mesmo tempo (e não apenas em sockets, mas em objetos stream genéricos que suportam polling). Exemplo:

# 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

Diferença em relação ao CPython

O CPython levanta uma exceção socket.timeout em caso de timeout, que é uma subclasse de OSError. O MicroPython levanta um OSError diretamente. Se você usar except OSError: para capturar a exceção, seu código funcionará tanto no MicroPython quanto no CPython.

setblocking(flag: bool) None

Define o modo bloqueante ou não bloqueante do socket: se flag for falso, o socket é definido como não bloqueante, caso contrário como bloqueante.

Este método é um atalho para certas chamadas de settimeout():

  • sock.setblocking(True) é equivalente a sock.settimeout(None)

  • sock.setblocking(False) é equivalente a sock.settimeout(0)

makefile(mode: str = 'rb', buffering: int = 0, /) Any

Retorna um objeto de arquivo associado ao socket. O tipo exato retornado depende dos argumentos fornecidos a makefile(). O suporte é limitado apenas a modos binários (‘rb’, ‘wb’ e ‘rwb’). Os argumentos do CPython encoding, errors e newline não são suportados.

Diferença em relação ao CPython

Como o MicroPython não suporta streams com buffer, os valores do parâmetro buffering são ignorados e tratados como se fossem 0 (sem buffer).

Diferença em relação ao CPython

Fechar o objeto de arquivo retornado por makefile() TAMBÉM fechará o socket original.

read(size: int | None = None) bytes

Lê até size bytes do socket. Retorna um objeto bytes. Se size não for fornecido, lê todos os dados disponíveis do socket até EOF; assim sendo, o método não retornará até que o socket seja fechado. Esta função tenta ler tantos dados quanto solicitado (sem “short reads”). Isso pode não ser possível com um socket não bloqueante, e então menos dados serão retornados.

readinto(buf: bytearray | memoryview, nbytes: int | None = None) int

Lê bytes para dentro de buf. Se nbytes for especificado, lê no máximo essa quantidade de bytes. Caso contrário, lê no máximo len(buf) bytes. Assim como read(), este método segue a política de “sem short reads”.

Valor de retorno: número de bytes lidos e armazenados em buf.

readline() bytes

Lê uma linha, terminando em um caractere de nova linha.

Valor de retorno: a linha lida.

write(buf: bytes) int

Escreve o buffer de bytes no socket. Esta função tentará escrever todos os dados em um socket (sem “short writes”). Isso pode não ser possível com um socket não bloqueante, e o valor retornado será menor que o comprimento de buf.

Valor de retorno: número de bytes escritos.

Nota

O MicroPython não implementa socket.error. O CPython tem uma exceção socket.error obsoleta que é um alias de OSError; no MicroPython, use OSError diretamente para capturar erros relacionados a sockets.