socket — модуль сокетів¶
Цей модуль надає доступ до інтерфейсу BSD-сокетів.
Відмінність від CPython
Для ефективності та узгодженості об’єкти сокетів у MicroPython безпосередньо реалізують інтерфейс stream (подібний до файлу). У CPython необхідно перетворити сокет на файлоподібний об’єкт за допомогою методу makefile(). Цей метод усе ще підтримується MicroPython (але є холостою операцією), тому де важлива сумісність з CPython, переконайтеся, що використовуєте його.
Формат(и) адреси сокета¶
Нативний формат адреси сокета модуля socket — це непрозорий тип даних, що повертається функцією getaddrinfo(), яка повинна використовуватися для розв’язання текстових адрес (включаючи числові адреси):
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)
Використання getaddrinfo() є найефективнішим (як з точки зору пам’яті, так і обчислювальної потужності) і переносимим способом роботи з адресами.
Модуль socket також надає сумісний з CPython спосіб задавати адреси за допомогою кортежів, як описано нижче. На OpenMV Cam модуль socket вбудований; числові адреси можна задавати безпосередньо у форматі кортежів, але доменні імена спочатку слід розв’язати за допомогою getaddrinfo().
Підсумовуючи:
Завжди використовуйте
getaddrinfo()для розв’язання імен хостів.Адреси у вигляді кортежів, описані нижче, можна використовувати як скорочення для числових адрес, для швидких перевірок та інтерактивного використання.
Формат адреси у вигляді кортежу для модуля socket:
IPv4: (ipv4_address, port), де ipv4_address — рядок з числовою IPv4-адресою у крапково-десятковій нотації, наприклад
"8.8.8.8", а port — ціле число порту в діапазоні 1-65535. Доменні імена не приймаються як ipv4_address; спочатку розв’яжіть їх за допомогоюgetaddrinfo().IPv6: (ipv6_address, port, flowinfo, scopeid), де ipv6_address — рядок з числовою IPv6-адресою у двокрапковій нотації, наприклад
"2001:db8::1", а port — ціле число порту в діапазоні 1-65535. flowinfo має бути 0. scopeid — ідентифікатор області інтерфейсу для адрес з локальним зв’язком. Доменні імена не приймаються як ipv6_address; спочатку розв’яжіть їх за допомогоюgetaddrinfo().
Функції¶
- socket.getaddrinfo(host: str, port: int, af: int = 0, type: int = 0, proto: int = 0, flags: int = 0, /) List[Tuple]¶
Перетворити аргумент хоста/порту в послідовність 5-кортежів, що містять усі необхідні аргументи для створення сокета, підключеного до цієї служби. Аргументи af, type та proto (які мають те саме значення, що й для функції
socket) можна використовувати для фільтрації типів адрес, що повертаються. Якщо параметр не вказано або дорівнює нулю, можуть повертатися всі комбінації адрес (потребує фільтрації на стороні користувача).Отриманий список 5-кортежів має таку структуру:
(family, type, proto, canonname, sockaddr)Наступний приклад показує, як підключитися до заданої 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])
Рекомендоване використання параметрів фільтрації:
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])
Відмінність від CPython
CPython викликає виняток
socket.gaierror(підкласOSError) у разі помилки в цій функції. MicroPython не маєsocket.gaierrorі безпосередньо викликає OSError. Зауважте, що номери помилокgetaddrinfo()утворюють окремий простір імен і можуть не збігатися з номерами помилок з модуляerrno. Щоб відрізнити помилкиgetaddrinfo(), вони представлені від’ємними числами, тоді як стандартні системні помилки — додатними числами (номери помилок доступні за допомогою властивостіe.args[0]з об’єкта винятку). Використання від’ємних значень є тимчасовою деталлю, яка може змінитися в майбутньому.
Константи¶
- socket.IPPROTO_IP: int¶
Рівень IP-протоколу. Використовується як аргумент level для
setsockopt()разом з параметрамиIP_*.
- socket.IPPROTO_TCP: int¶
Протокол TCP. Не потрібно передавати його до
socket(тип сокетаSOCK_STREAMвибирає його автоматично); його єдине реальне використання — як аргумент level дляsetsockopt()разом з параметрамиTCP_*.
- socket.SOL_SOCKET: int¶
Рівень параметрів сокета. Використовується як аргумент level для
setsockopt()разом з параметрамиSO_*.
- socket.SO_REUSEADDR: int¶
Дозволити сокету прив’язатися до адреси/порту, що все ще перебуває в стані
TIME_WAIT.
- socket.SO_SNDTIMEO: int¶
Тайм-аут надсилання в мілісекундах, що передається як аргумент value до
setsockopt().
- socket.SO_RCVTIMEO: int¶
Тайм-аут отримання в мілісекундах, що передається як аргумент value до
setsockopt().
- socket.IP_ADD_MEMBERSHIP: int¶
Приєднатися до групи розсилки. Параметр
setsockopt()рівняIPPROTO_IP.
- socket.IP_DROP_MEMBERSHIP: int¶
Вийти з групи розсилки. Параметр
setsockopt()рівняIPPROTO_IP.
- socket.TCP_NODELAY: int¶
Вимкнути алгоритм Нейгла. Параметр
setsockopt()рівняIPPROTO_TCP.
- socket.MSG_PEEK: int¶
Для
recv()/recvfrom(): повернути дані без їх видалення з черги введення.
- socket.MSG_DONTWAIT: int¶
Для
recv()/recvfrom(): виконати операцію в неблокуючому режимі.
Класи¶
- class socket.socket(af: int = AF_INET, type: int = SOCK_STREAM, proto: int = IPPROTO_TCP, /)¶
Створити новий сокет з використанням заданого сімейства адрес, типу сокета та номера протоколу. У більшості випадків задавати proto не потрібно (і не рекомендується); аргумент type автоматично вибирає необхідний протокол:
# Create STREAM TCP socket socket(AF_INET, SOCK_STREAM) # Create DGRAM UDP socket socket(AF_INET, SOCK_DGRAM)
- close() None¶
Позначити сокет як закритий та звільнити всі ресурси. Після цього всі подальші операції з об’єктом сокета завершаться невдачею. Відділений кінець отримає індикацію EOF, якщо це підтримується протоколом.
Сокети автоматично закриваються при зборі сміття, але рекомендується явно викликати
close()для них, як тільки ви закінчили роботу з ними.
- listen(backlog: int = 2) None¶
Дозволити серверу приймати підключення. Якщо backlog вказано, воно має бути щонайменше 0 (якщо менше, буде встановлено 0); визначає кількість неприйнятих підключень, які система дозволить до відхилення нових. Якщо не вказано, вибирається розумне значення за замовчуванням.
- accept() Tuple['socket', Tuple]¶
Прийняти підключення. Сокет повинен бути прив’язаний до адреси і очікувати підключень. Повертається пара (conn, address), де conn — це новий об’єкт сокета, що використовується для надсилання та отримання даних через підключення, а address — адреса, прив’язана до сокета на іншому кінці підключення.
- send(bytes: bytes) int¶
Надіслати дані через сокет. Сокет повинен бути підключений до віддаленого сокета. Повертає кількість надісланих байтів, яка може бути меншою за довжину даних («коротке записування»).
- sendall(bytes: bytes) None¶
Надіслати всі дані через сокет. Сокет повинен бути підключений до віддаленого сокета. На відміну від
send(), цей метод намагатиметься надіслати всі дані, надсилаючи їх частинами послідовно.Поведінка цього методу на неблокуючих сокетах не визначена. Через це в MicroPython рекомендується використовувати замість нього метод
write(), який має ту саму політику «без коротких записів» для блокуючих сокетів і повертає кількість надісланих байтів для неблокуючих сокетів.
- recv(bufsize: int, flags: int = 0) bytes¶
Отримати дані з сокета. Повертається об’єкт bytes, що представляє отримані дані. Максимальна кількість даних, що отримуються за один раз, визначається параметром bufsize.
Необов’язковий аргумент flags — побітове АБО прапорів повідомлення (
MSG_PEEK,MSG_DONTWAIT), які мають те саме значення, що й у CPython.
- sendto(bytes: bytes, address: Any) int¶
Надіслати дані через сокет. Сокет не повинен бути підключений до віддаленого сокета, оскільки цільовий сокет визначається аргументом address.
- recvfrom(bufsize: int, flags: int = 0) Tuple[bytes, Tuple]¶
Отримати дані з сокета. Повертається пара (bytes, address), де bytes — об’єкт bytes, що представляє отримані дані, а address — адреса сокета, що надіслав дані.
Дивіться функцію
recv()для пояснення необов’язкового аргументу flags.
- setsockopt(level: int, optname: int, value: int | bytes) None¶
Встановити значення заданого параметра сокета. Необхідні символічні константи визначені в модулі socket (SO_* тощо). value може бути цілим числом або байтоподібним об’єктом, що представляє буфер.
- settimeout(value: float | None) None¶
Встановити тайм-аут для блокуючих операцій сокета. Аргумент value може бути невід’ємним числом з рухомою комою, що виражає секунди, або None. Якщо задано ненульове значення, подальші операції сокета викличуть виняток
OSError, якщо тайм-аут закінчився до завершення операції. Якщо задано нуль, сокет переводиться в неблокуючий режим. Якщо задано None, сокет переводиться в блокуючий режим.Переносимою та універсальною альтернативою є використання об’єкта
select.poll. Це дозволяє одночасно очікувати на кількох об’єктах (і не лише на сокетах, але й на загальних об’єктах stream, що підтримують опитування). Приклад:# 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
Відмінність від CPython
CPython викликає виняток
socket.timeoutу разі тайм-ауту, який є підкласомOSError. MicroPython безпосередньо викликає OSError. Якщо ви використовуєтеexcept OSError:для перехоплення винятку, ваш код працюватиме як у MicroPython, так і в CPython.
- setblocking(flag: bool) None¶
Встановити блокуючий або неблокуючий режим сокета: якщо flag є хибним, сокет переводиться в неблокуючий режим, інакше — в блокуючий.
Цей метод є скороченням для певних викликів
settimeout():sock.setblocking(True)еквівалентноsock.settimeout(None)sock.setblocking(False)еквівалентноsock.settimeout(0)
- makefile(mode: str = 'rb', buffering: int = 0, /) Any¶
Повернути файловий об’єкт, пов’язаний із сокетом. Точний повернутий тип залежить від аргументів, переданих до makefile(). Підтримка обмежена лише бінарними режимами („rb“, „wb“ та „rwb“). Аргументи CPython: encoding, errors та newline не підтримуються.
Відмінність від CPython
Оскільки MicroPython не підтримує буферизовані потоки, значення параметра buffering ігнорується і обробляється так, ніби воно дорівнює 0 (небуферизовано).
Відмінність від CPython
Закриття файлового об’єкта, повернутого функцією makefile(), ТАКОЖ закриє вихідний сокет.
- read(size: int | None = None) bytes¶
Прочитати до size байтів з сокета. Повертає об’єкт bytes. Якщо size не вказано, читає всі доступні дані з сокета до EOF; тому метод не повернеться до закриття сокета. Ця функція намагається прочитати стільки даних, скільки запитано (без «коротких читань»). Однак це може бути неможливим для неблокуючого сокета, і тоді буде повернено менше даних.
- readinto(buf: bytearray | memoryview, nbytes: int | None = None) int¶
Читати байти в buf. Якщо вказано nbytes, читати не більше ніж стільки байтів. Інакше читати не більше ніж len(buf) байтів. Як і
read(), цей метод дотримується політики «без коротких читань».Повернене значення: кількість прочитаних та збережених у buf байтів.