socket — moduł socket

Ten moduł udostępnia dostęp do interfejsu gniazd BSD.

Różnice względem CPythona

Ze względu na wydajność i spójność obiekty gniazd w MicroPythonie implementują interfejs stream (plikopodobny) bezpośrednio. W CPythonie należy przekształcić gniazdo w obiekt plikopodobny za pomocą metody makefile(). Ta metoda jest nadal obsługiwana przez MicroPythona (ale nic nie robi), więc tam, gdzie ma znaczenie zgodność z CPythonem, należy jej używać.

Format(y) adresu gniazda

Natywny format adresu gniazda modułu socket to nieprzezroczysty typ danych zwracany przez funkcję getaddrinfo(), której należy używać do rozwiązywania adresów tekstowych (w tym adresów liczbowych):

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)

Użycie getaddrinfo() to najbardziej wydajny (zarówno pod względem pamięci, jak i mocy obliczeniowej) oraz przenośny sposób pracy z adresami.

Moduł socket udostępnia również zgodny z CPythonem sposób określania adresów za pomocą krotek, opisany poniżej. W OpenMV Cam moduł socket jest wbudowany; adresy liczbowe mogą być podawane bezpośrednio w formacie krotki, ale nazwy domenowe muszą najpierw zostać rozwiązane za pomocą getaddrinfo().

Podsumowując:

  • Zawsze używaj getaddrinfo() do rozwiązywania nazw hostów.

  • Adresy w postaci krotek opisane poniżej mogą służyć jako skrót dla adresów liczbowych, do szybkich rozwiązań i użycia interaktywnego.

Format adresu w postaci krotki dla modułu socket:

  • IPv4: (ipv4_address, port), gdzie ipv4_address to łańcuch z liczbowym adresem IPv4 w notacji kropkowej, np. "8.8.8.8", a port to całkowity numer portu z zakresu 1-65535. Nazwy domenowe nie są akceptowane jako ipv4_address; najpierw rozwiąż je za pomocą getaddrinfo().

  • IPv6: (ipv6_address, port, flowinfo, scopeid), gdzie ipv6_address to łańcuch z liczbowym adresem IPv6 w notacji dwukropkowej, np. "2001:db8::1", a port to całkowity numer portu z zakresu 1-65535. flowinfo musi wynosić 0. scopeid to identyfikator zakresu interfejsu dla adresów link-local. Nazwy domenowe nie są akceptowane jako ipv6_address; najpierw rozwiąż je za pomocą getaddrinfo().

Funkcje

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

Tłumaczy argument host/port na sekwencję 5-elementowych krotek zawierających wszystkie argumenty niezbędne do utworzenia gniazda połączonego z tą usługą. Argumenty af, type oraz proto (które mają takie samo znaczenie jak dla funkcji socket) mogą służyć do filtrowania rodzaju zwracanych adresów. Jeśli parametr nie zostanie podany lub wynosi zero, mogą zostać zwrócone wszystkie kombinacje adresów (wymagające filtrowania po stronie użytkownika).

Wynikowa lista 5-elementowych krotek ma następującą strukturę:

(family, type, proto, canonname, sockaddr)

Poniższy przykład pokazuje, jak połączyć się z podanym adresem 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])

Zalecane użycie parametrów filtrujących:

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

Różnice względem CPythona

CPython zgłasza wyjątek socket.gaierror (podklasa OSError) w przypadku błędu w tej funkcji. MicroPython nie ma socket.gaierror i zgłasza OSError bezpośrednio. Zwróć uwagę, że numery błędów getaddrinfo() tworzą odrębną przestrzeń nazw i mogą nie pasować do numerów błędów z modułu errno. Aby odróżnić błędy getaddrinfo(), są one reprezentowane przez liczby ujemne, podczas gdy standardowe błędy systemowe są liczbami dodatnimi (numery błędów są dostępne za pomocą właściwości e.args[0] obiektu wyjątku). Użycie wartości ujemnych jest rozwiązaniem tymczasowym, które może ulec zmianie w przyszłości.

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

Konwertuje binarny adres sieciowy bin_addr z podanej rodziny adresów af na reprezentację tekstową:

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

Konwertuje tekstowy adres sieciowy txt_addr z podanej rodziny adresów af na reprezentację binarną:

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

Stałe

socket.AF_INET: int

Rodzina adresów IPv4.

socket.AF_INET6: int

Rodzina adresów IPv6.

socket.SOCK_STREAM: int

Strumieniowy typ gniazda (TCP).

socket.SOCK_DGRAM: int

Datagramowy typ gniazda (UDP).

socket.SOCK_RAW: int

Surowy typ gniazda.

socket.IPPROTO_IP: int

Poziom protokołu IP. Używany jako argument level dla setsockopt() wraz z opcjami IP_*.

socket.IPPROTO_TCP: int

Protokół TCP. Nie trzeba przekazywać go do socket (typ gniazda SOCK_STREAM wybiera go automatycznie); jego jedynym rzeczywistym zastosowaniem jest argument level dla setsockopt() wraz z opcjami TCP_*.

socket.SOL_SOCKET: int

Poziom opcji gniazda. Używany jako argument level dla setsockopt() wraz z opcjami SO_*.

socket.SO_REUSEADDR: int

Pozwala gniazdu powiązać się z adresem/portem, który wciąż znajduje się w stanie TIME_WAIT.

socket.SO_BROADCAST: int

Zezwala na wysyłanie datagramów na adres rozgłoszeniowy.

socket.SO_KEEPALIVE: int

Włącza okresowe wysyłanie sond keep-alive na połączonym gnieździe.

socket.SO_SNDTIMEO: int

Limit czasu wysyłania, w milisekundach, przekazywany jako argument value do setsockopt().

socket.SO_RCVTIMEO: int

Limit czasu odbioru, w milisekundach, przekazywany jako argument value do setsockopt().

socket.IP_ADD_MEMBERSHIP: int

Dołącza do grupy multicast. Opcja setsockopt() poziomu IPPROTO_IP.

socket.IP_DROP_MEMBERSHIP: int

Opuszcza grupę multicast. Opcja setsockopt() poziomu IPPROTO_IP.

socket.TCP_NODELAY: int

Wyłącza algorytm Nagle’a. Opcja setsockopt() poziomu IPPROTO_TCP.

socket.MSG_PEEK: int

Dla recv() / recvfrom(): zwraca dane bez usuwania ich z kolejki wejściowej.

socket.MSG_DONTWAIT: int

Dla recv() / recvfrom(): wykonuje operację w trybie nieblokującym.

Klasy

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

Tworzy nowe gniazdo o podanej rodzinie adresów, typie gniazda i numerze protokołu. Określanie proto w większości przypadków nie jest wymagane (i niezalecane); argument type wybiera potrzebny protokół automatycznie:

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

Oznacza gniazdo jako zamknięte i zwalnia wszystkie zasoby. Gdy to nastąpi, wszystkie przyszłe operacje na obiekcie gniazda zakończą się niepowodzeniem. Zdalny koniec otrzyma sygnalizację EOF, jeśli jest obsługiwana przez protokół.

Gniazda są automatycznie zamykane podczas odśmiecania pamięci, ale zaleca się jawne wywoływanie na nich close() od razu po zakończeniu pracy z nimi.

bind(address: Any) None

Wiąże gniazdo z address. Gniazdo nie może być już powiązane.

listen(backlog: int = 2) None

Umożliwia serwerowi akceptowanie połączeń. Jeśli określono backlog, musi on wynosić co najmniej 0 (jeśli jest niższy, zostanie ustawiony na 0); określa liczbę niezaakceptowanych połączeń, które system dopuści, zanim odrzuci nowe połączenia. Jeśli nie zostanie określony, wybierana jest domyślna rozsądna wartość.

accept() Tuple['socket', Tuple]

Akceptuje połączenie. Gniazdo musi być powiązane z adresem i nasłuchiwać połączeń. Wartością zwracaną jest para (conn, address), gdzie conn to nowy obiekt gniazda przydatny do wysyłania i odbierania danych na połączeniu, a address to adres powiązany z gniazdem na drugim końcu połączenia.

connect(address: Any) None

Łączy się ze zdalnym gniazdem pod adresem address.

send(bytes: bytes) int

Wysyła dane do gniazda. Gniazdo musi być połączone ze zdalnym gniazdem. Zwraca liczbę wysłanych bajtów, która może być mniejsza niż długość danych („short write”).

sendall(bytes: bytes) None

Wysyła wszystkie dane do gniazda. Gniazdo musi być połączone ze zdalnym gniazdem. W odróżnieniu od send(), ta metoda spróbuje wysłać wszystkie dane, wysyłając je kolejno fragment po fragmencie.

Zachowanie tej metody na gniazdach nieblokujących jest niezdefiniowane. Z tego powodu w MicroPythonie zaleca się zamiast tego użycie metody write(), która stosuje tę samą zasadę „brak short writes” dla gniazd blokujących i zwraca liczbę wysłanych bajtów na gniazdach nieblokujących.

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

Odbiera dane z gniazda. Wartością zwracaną jest obiekt bytes reprezentujący odebrane dane. Maksymalną ilość danych odbieranych jednorazowo określa parametr bufsize.

Opcjonalny argument flags to bitowe OR flag komunikatu (MSG_PEEK, MSG_DONTWAIT), które mają takie samo znaczenie jak w CPythonie.

sendto(bytes: bytes, address: Any) int

Wysyła dane do gniazda. Gniazdo nie powinno być połączone ze zdalnym gniazdem, ponieważ docelowe gniazdo jest określone przez address.

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

Odbiera dane z gniazda. Wartością zwracaną jest para (bytes, address), gdzie bytes to obiekt bytes reprezentujący odebrane dane, a address to adres gniazda wysyłającego dane.

Zobacz funkcję recv(), aby uzyskać wyjaśnienie opcjonalnego argumentu flags.

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

Ustawia wartość podanej opcji gniazda. Potrzebne stałe symboliczne są zdefiniowane w module socket (SO_* itp.). value może być liczbą całkowitą lub obiektem bajtopodobnym reprezentującym bufor.

settimeout(value: float | None) None

Ustawia limit czasu dla blokujących operacji gniazda. Argument value może być nieujemną liczbą zmiennoprzecinkową wyrażającą sekundy lub None. Jeśli podana zostanie wartość niezerowa, kolejne operacje gniazda zgłoszą wyjątek OSError, jeśli wartość okresu limitu czasu upłynie, zanim operacja zostanie zakończona. Jeśli podane zostanie zero, gniazdo zostanie przełączone w tryb nieblokujący. Jeśli podane zostanie None, gniazdo zostanie przełączone w tryb blokujący.

Przenośną i uniwersalną alternatywą jest użycie obiektu select.poll. Pozwala on oczekiwać na wiele obiektów jednocześnie (i to nie tylko na gniazda, ale na ogólne obiekty stream obsługujące odpytywanie). Przykład:

# 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

Różnice względem CPythona

CPython zgłasza wyjątek socket.timeout w przypadku przekroczenia limitu czasu, który jest podklasą OSError. MicroPython zgłasza zamiast tego OSError bezpośrednio. Jeśli użyjesz except OSError: do przechwycenia wyjątku, twój kod będzie działać zarówno w MicroPythonie, jak i CPythonie.

setblocking(flag: bool) None

Ustawia tryb blokujący lub nieblokujący gniazda: jeśli flaga jest fałszywa, gniazdo zostaje ustawione w tryb nieblokujący, w przeciwnym razie w tryb blokujący.

Ta metoda jest skrótem dla pewnych wywołań settimeout():

  • sock.setblocking(True) jest równoważne sock.settimeout(None)

  • sock.setblocking(False) jest równoważne sock.settimeout(0)

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

Zwraca obiekt pliku powiązany z gniazdem. Dokładny zwracany typ zależy od argumentów podanych do makefile(). Obsługa jest ograniczona wyłącznie do trybów binarnych («rb», «wb» oraz «rwb»). Argumenty CPythona: encoding, errors oraz newline nie są obsługiwane.

Różnice względem CPythona

Ponieważ MicroPython nie obsługuje strumieni buforowanych, wartość parametru buffering jest ignorowana i traktowana tak, jakby wynosiła 0 (bez buforowania).

Różnice względem CPythona

Zamknięcie obiektu pliku zwróconego przez makefile() ZAMKNIE również oryginalne gniazdo.

read(size: int | None = None) bytes

Czyta do size bajtów z gniazda. Zwraca obiekt bytes. Jeśli size nie zostanie podany, czyta wszystkie dane dostępne w gnieździe aż do EOF; w związku z tym metoda nie zakończy działania, dopóki gniazdo nie zostanie zamknięte. Ta funkcja próbuje odczytać tyle danych, ile zażądano (brak „short reads”). Może to jednak nie być możliwe na gnieździe nieblokującym, i wtedy zwrócone zostanie mniej danych.

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

Czyta bajty do buf. Jeśli określono nbytes, czyta co najwyżej tyle bajtów. W przeciwnym razie czyta co najwyżej len(buf) bajtów. Podobnie jak read(), ta metoda stosuje zasadę „brak short reads”.

Wartość zwracana: liczba bajtów odczytanych i zapisanych do buf.

readline() bytes

Czyta wiersz zakończony znakiem nowej linii.

Wartość zwracana: odczytany wiersz.

write(buf: bytes) int

Zapisuje bufor bajtów do gniazda. Ta funkcja spróbuje zapisać wszystkie dane do gniazda (brak „short writes”). Może to jednak nie być możliwe na gnieździe nieblokującym, i wtedy zwrócona wartość będzie mniejsza niż długość buf.

Wartość zwracana: liczba zapisanych bajtów.

Informacja

MicroPython nie implementuje socket.error. CPython ma przestarzały wyjątek socket.error będący aliasem OSError; w MicroPythonie użyj OSError bezpośrednio do przechwytywania błędów związanych z gniazdami.