socket — модуль 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]

Преобразует аргумент host/port в последовательность 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.inet_ntop(af: int, bin_addr: bytes) str

Преобразует двоичный сетевой адрес bin_addr заданного семейства адресов af в текстовое представление:

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

Преобразует текстовый сетевой адрес txt_addr заданного семейства адресов af в двоичное представление:

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

Константы

socket.AF_INET: int

Семейство адресов IPv4.

socket.AF_INET6: int

Семейство адресов IPv6.

socket.SOCK_STREAM: int

Потоковый (TCP) тип сокета.

socket.SOCK_DGRAM: int

Дейтаграммный (UDP) тип сокета.

socket.SOCK_RAW: int

Сырой (raw) тип сокета.

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_BROADCAST: int

Разрешает отправку дейтаграмм на широковещательный адрес.

socket.SO_KEEPALIVE: int

Включает периодическую передачу проб keep-alive на подключённом сокете.

socket.SO_SNDTIMEO: int

Тайм-аут отправки, в миллисекундах, передаваемый в качестве аргумента value для setsockopt().

socket.SO_RCVTIMEO: int

Тайм-аут приёма, в миллисекундах, передаваемый в качестве аргумента value для setsockopt().

socket.IP_ADD_MEMBERSHIP: int

Присоединиться к группе multicast. Параметр setsockopt() уровня IPPROTO_IP.

socket.IP_DROP_MEMBERSHIP: int

Покинуть группу multicast. Параметр 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(), как только вы закончили работать с ними.

bind(address: Any) None

Привязывает сокет к address. Сокет не должен быть уже привязан.

listen(backlog: int = 2) None

Позволяет серверу принимать соединения. Если указан backlog, он должен быть не менее 0 (если он меньше, он будет установлен в 0); и задаёт количество непринятых соединений, которые система разрешит, прежде чем отклонять новые соединения. Если не указан, выбирается разумное значение по умолчанию.

accept() Tuple['socket', Tuple]

Принимает соединение. Сокет должен быть привязан к адресу и слушать соединения. Возвращаемое значение — это пара (conn, address), где conn — это новый объект сокета, пригодный для отправки и приёма данных по соединению, а address — это адрес, привязанный к сокету на другом конце соединения.

connect(address: Any) None

Подключается к удалённому сокету по адресу 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 равен false, сокет устанавливается в неблокирующий режим, иначе — в блокирующий.

Этот метод является сокращением для определённых вызовов 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 байтов.

readline() bytes

Читает строку, заканчивающуюся символом новой строки.

Возвращаемое значение: прочитанная строка.

write(buf: bytes) int

Записывает буфер байтов в сокет. Эта функция попытается записать все данные в сокет (без «коротких записей»). Однако это может быть невозможно с неблокирующим сокетом, и возвращаемое значение будет меньше длины buf.

Возвращаемое значение: количество записанных байтов.

Примечание

MicroPython не реализует socket.error. В CPython есть устаревшее исключение socket.error, которое является псевдонимом OSError; в MicroPython используйте OSError напрямую для перехвата ошибок, связанных с сокетами.