socket — módulo socket

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

Diferença para o CPython

Por razões de eficiência e consistência, os objetos socket no MicroPython implementam diretamente uma interface stream (semelhante a ficheiro). No CPython, é necessário converter um socket num objeto semelhante a ficheiro utilizando o método makefile(). Este método ainda é suportado pelo MicroPython (mas não tem efeito), pelo que, quando a compatibilidade com o CPython for importante, certifique-se de que o utiliza.

Formato(s) de endereço de socket

O formato de endereço de socket nativo do módulo socket é um tipo de dados opaco devolvido pela função getaddrinfo(), que deve ser utilizada 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)

Utilizar getaddrinfo() é a forma mais eficiente (tanto em termos de memória como de capacidade de processamento) e portátil de trabalhar com endereços.

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

Em resumo:

  • Utilize sempre getaddrinfo() para resolver nomes de host.

  • Os endereços em tuplo descritos abaixo podem ser utilizados como atalho para endereços numéricos, para soluções rápidas e utilização interativa.

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

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

  • IPv6: (ipv6_address, port, flowinfo, scopeid), onde ipv6_address é uma string com o 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 âmbito de interface para endereços locais de ligação. Os nomes de domínio não são aceites como ipv6_address; resolva-os primeiro utilizando 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 numa sequência de 5-tuplos que contêm todos os argumentos necessários para criar um socket ligado a esse serviço. Os argumentos af, type e proto (que têm o mesmo significado que para a função socket) podem ser utilizados para filtrar que tipo de endereços são devolvidos. Se um parâmetro não for especificado ou for zero, podem ser devolvidas todas as combinações de endereços (exigindo filtragem do lado do utilizador).

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

(family, type, proto, canonname, sockaddr)

O exemplo seguinte mostra como ligar a um determinado 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])

Utilização recomendada 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 para o CPython

O CPython lança uma exceção socket.gaierror (subclasse de OSError) em caso de erro nesta função. O MicroPython não tem socket.gaierror e lança OSError diretamente. Note que os números de erro de getaddrinfo() formam um espaço de nomes separado e podem não corresponder aos números de erro do módulo errno. Para distinguir os erros de getaddrinfo(), estes são representados por números negativos, enquanto os erros de sistema padrão são números positivos (os números de erro são acessíveis utilizando a propriedade e.args[0] de um objeto de exceção). A utilização de valores negativos é um detalhe provisório que pode ser alterado 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 para 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 para 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 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. Utilizado como argumento level para setsockopt() juntamente com as opções IP_*.

socket.IPPROTO_TCP: int

O protocolo TCP. Não é necessário passá-lo para socket (o tipo de socket SOCK_STREAM seleciona-o automaticamente); a sua única utilização real é como argumento level para setsockopt() juntamente com as opções TCP_*.

socket.SOL_SOCKET: int

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

socket.SO_REUSEADDR: int

Permite que o socket seja vinculado a um endereço/porta que ainda se encontra no estado TIME_WAIT.

socket.SO_BROADCAST: int

Permite o envio de datagramas para um endereço de difusão.

socket.SO_KEEPALIVE: int

Ativa a transmissão periódica de sondas de keep-alive num socket ligado.

socket.SO_SNDTIMEO: int

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

socket.SO_RCVTIMEO: int

Timeout de receção, em milissegundos, passado como argumento value para setsockopt().

socket.IP_ADD_MEMBERSHIP: int

Junta-se a um grupo multicast. Opção setsockopt() ao nível IPPROTO_IP.

socket.IP_DROP_MEMBERSHIP: int

Abandona um grupo multicast. Opção setsockopt() ao nível IPPROTO_IP.

socket.TCP_NODELAY: int

Desativa o algoritmo de Nagle. Opção setsockopt() ao nível IPPROTO_TCP.

socket.MSG_PEEK: int

Para recv() / recvfrom(): devolve dados sem os remover 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 utilizando 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 (nem recomendado); o argumento type seleciona automaticamente o protocolo necessário:

# 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 liberta todos os recursos. Após isso, todas as operações futuras no objeto socket falharão. O extremo remoto receberá indicação de EOF se suportado pelo protocolo.

Os sockets são fechados automaticamente quando são recolhidos pelo garbage collector, mas recomenda-se que sejam fechados explicitamente com close() logo que termine de trabalhar com eles.

bind(address: Any) None

Vincula o socket a address. O socket não deve estar já vinculado.

listen(backlog: int = 2) None

Habilita um servidor a aceitar ligações. Se backlog for especificado, deve ser pelo menos 0 (se for inferior, será definido como 0); e especifica o número de ligações não aceites que o sistema permitirá antes de recusar novas ligações. Se não for especificado, é escolhido um valor predefinido razoável.

accept() Tuple['socket', Tuple]

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

connect(address: Any) None

Liga a um socket remoto em address.

send(bytes: bytes) int

Envia dados para o socket. O socket deve estar ligado a um socket remoto. Devolve o número de bytes enviados, que pode ser inferior ao comprimento dos dados («short write»).

sendall(bytes: bytes) None

Envia todos os dados para o socket. O socket deve estar ligado a um socket remoto. Ao contrário de send(), este método tentará enviar todos os dados, enviando os dados em partes consecutivas.

O comportamento deste método em sockets não bloqueantes não é definido. Por este motivo, no MicroPython, recomenda-se utilizar o método write(), que tem a mesma política de «sem short writes» para sockets bloqueantes e devolverá 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 que representa os dados recebidos. A quantidade máxima de dados a receber 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 ligado a um socket remoto, pois 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 que representa os dados recebidos e address é o endereço do socket que envia os dados.

Consulte a função recv() para obter 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 estão definidas no módulo socket (SO_* etc.). O value pode ser um número inteiro ou um objeto semelhante a bytes que representa 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 que exprime segundos, ou None. Se for fornecido um valor diferente de zero, as operações de socket subsequentes lançarão uma exceção OSError se o período de timeout tiver decorrido antes de a operação ter sido concluída. Se for fornecido zero, o socket é colocado em modo não bloqueante. Se for fornecido None, o socket é colocado em modo bloqueante.

Uma alternativa portátil e genérica é utilizar um objeto select.poll. Isto permite aguardar por múltiplos objetos ao mesmo tempo (e não apenas em sockets, mas em objetos stream genéricos que suportem 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 para o CPython

O CPython lança uma exceção socket.timeout em caso de timeout, que é uma subclasse de OSError. O MicroPython lança um OSError diretamente. Se utilizar except OSError: para capturar a exceção, o seu código funcionará tanto no MicroPython como 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, é definido 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

Devolve um objeto ficheiro associado ao socket. O tipo exato devolvido depende dos argumentos fornecidos a makefile(). O suporte está limitado apenas aos modos binários (“rb”, “wb” e “rwb”). Os argumentos do CPython: encoding, errors e newline não são suportados.

Diferença para o 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 para o CPython

Fechar o objeto ficheiro devolvido por makefile() VAI fechar também o socket original.

read(size: int | None = None) bytes

Lê até size bytes do socket. Devolve um objeto bytes. Se size não for fornecido, lê todos os dados disponíveis no socket até ao EOF; como tal, o método não retornará até que o socket seja fechado. Esta função tenta ler tantos dados quanto os solicitados (sem «short reads»). Isto pode não ser possível com um socket não bloqueante, sendo devolvidos então menos dados.

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

Lê bytes para buf. Se nbytes for especificado, lê no máximo esse número de bytes. Caso contrário, lê no máximo len(buf) bytes. Tal 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, terminada num carácter 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 num socket (sem «short writes»). Isto pode não ser possível com um socket não bloqueante, sendo o valor devolvido inferior ao 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, utilize OSError diretamente para capturar erros relacionados com sockets.