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