Функции

getaddrinfo

Функция getaddrinfo(host, port, af=0, type=0, proto=0, flags=0) Преобразует аргументы host и port в последовательность 5-кортежей, содержащих все необходимые аргументы для создания сокета, подключённого к этому сервису. Аргументы af, type и proto (которые имеют то же значение, что и в функции socket()) могут использоваться для фильтрации адресов, которые будут возвращены. Если параметр не указан или равен нулю, возвращаются все возможные комбинации адресов (требуется фильтрация результатов со стороны пользователя).

Результирующий список из 5-кортежей имеет следующую структуру:

  (family, type, proto, canonname, sockaddr)
  

Следующий пример показывает, как выполнить подключение к указанному URL:

  s = socket.socket()
# Предполагается, что если "type" не указан, будет возвращён
# адрес для SOCK_STREAM — это может быть неверным.
addr = socket.getaddrinfo('telematic.dev', 80)[0][-1]
s.connect(addr)
  

Рекомендуемый способ использования с параметрами фильтрации:

  s = socket.socket()
# Гарантированно вернёт адрес, подходящий для connect с целью
# поточной (stream) работы.
addr = socket.getaddrinfo('telematic.dev', 80, 0, SOCK_STREAM)[0][-1]
s.connect(addr)
  

Отличие от CPython В случае ошибки в этой функции CPython генерирует исключение socket.gaierror (подкласс OSError).
MicroPython вместо этого генерирует исключение OSError напрямую. Обратите внимание, что номера ошибок, возвращаемых getaddrinfo(), находятся в отдельном пространстве имён и могут не совпадать с номерами ошибок из модуля errno. Чтобы отличить ошибки getaddrinfo(), они представлены отрицательными номерами. В то же время стандартные системные ошибки имеют положительные значения (номера ошибок доступны через свойство e.args[0] из объекта исключения).


gethostbyname

Функция gethostbyname(hostname) возвращает IPv4 адрес хоста/домена hostname в формат строки. Если имя хоста hostname является IPv4-адресом, то оно возвращается без изменений.

Функция gethostbyname() не поддерживает разрешение имен IPv6-адресов, для поддержки двойного стека IPv4/v6 следует использовать функцию socket.getaddrinfo().

  from net import gethostbyname
print(gethostbyname('ya.ru'))         # 77.88.44.242
print(gethostbyname('google.com'))    # 173.194.221.100
  

Классы

socket

Класс socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP) является основным элементом для работы с сетевыми интерфейсами. Сокет можно создать для работы как с TCP, так и с UDP соединениями.

Аргументы:

  • family (опционально): Указывает семейство протоколов. Возможные значения:
    • socket.AF_INET — IPv4 (по умолчанию).
    • socket.AF_INET6 — IPv6 (поддержка зависит от реализации).
  • type (опционально): Указывает тип сокетов. Возможные значения:
    • socket.SOCK_STREAM — Транспорт TCP (по умолчанию).
    • socket.SOCK_DGRAM — Транспорт UDP.

Указание proto в большинстве случаев не требуется. Вместо этого параметр type выбирает нужный протокол автоматически:

  # Создать TCP-сокет поточного типа (STREAM)
socket(AF_INET, SOCK_STREAM)
# Создать UDP-сокет датаграммного типа (DGRAM)
socket(AF_INET, SOCK_DGRAM)
  

Метод bind(address) привязывает сокет к указанному сетевому адресу.

  • address — Кортеж (host, port), где host — IP-адрес устройства (или пустая строка "" для всех интерфейсов), а port — номер порта.
  s = socket.socket()
s.bind(('0.0.0.0', 8080))
  

Метод listen(backlog) переводит сокет в режим “сервер”, чтобы принимать входящие соединения (только для TCP).

  • backlog — Максимальное количество ожидающих подключений.
  s.listen(5)
  

Метод accept() ожидает входящее соединение и возвращает (conn, address):

  • conn — Новый сокет для взаимодействия с клиентом.
  • address — Адрес клиента в формате (host, port).
  conn, addr = s.accept()
print('Новое соединение от:', addr)
  

Метод connect(address) устанавливает соединение с сервером.

  • address — Кортеж (host, port), где host — IP-адрес сервера, а port — номер порта.
  s.connect(('192.168.1.10', 8080))
  

Метод send(data) отправляет данные через соединение (для TCP).

  • data — Байтовая строка для отправки.
  s.send(b'Hello, server!')
  

Метод sendto(data, address) отправляет данные через соединение UDP.

  • data — Байтовая строка для отправки.
  • address — Кортеж (host, port) с адресом получателя.
  s.sendto(b'Hello, UDP!', ('192.168.1.10', 12345))
  

Метод recv(bufsize) получает данные от сокета.

  • bufsize — Размер буфера для приёма данных (в байтах).
  data = s.recv(1024)
print('Получено:', data)
  

Метод recvfrom(bufsize) получает данные от UDP-сокета.

  • bufsize — Размер буфера для приёма данных (в байтах).

Возвращает (data, address):

  • data — Принятая информация.
  • address — Адрес отправителя.
  data, address = s.recvfrom(1024)
print('Данные от', address, ':', data)
  

Метод close() закрывает сокет и освобождает ресурсы.

  s.close()
  

Метод setblocking(flag) устанавливает режим блокировки сокета.

  • flag: Если True (по умолчанию), сокет работает в блокирующем режиме. Если False, операции чтения/записи становятся неблокирующими.
  s.setblocking(False)
  

Метод setsockopt(level, optname, value) устанавливает параметры сокета.

  • level — Уровень протокола (обычно socket.SOL_SOCKET).
  • optname — Параметр настраиваемой опции.
  • value — Значение опции.
  s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  

Константы

Модуль socket содержит ряд стандартных констант:

  • Типы адресов:

    • socket.AF_INET — IPv4.
    • socket.AF_INET6 — IPv6.
  • Типы транспорта:

    • socket.SOCK_STREAM — TCP.
    • socket.SOCK_DGRAM — UDP.
  • Опции для setsockopt:

    • socket.SOL_SOCKET — Уровень настроек сокета.
    • socket.SO_REUSEADDR — Повторное использование локального адреса.

Примеры

Простой TCP-сервер

  import socket

# Создание сокета
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', 8080))
s.listen(1)  # Максимум 1 подключение

print('Ожидание подключения...')
conn, addr = s.accept()
print('Подключение от:', addr)

# Приём и отправка данных
data = conn.recv(1024)  # Приём данных
print('Получено:', data.decode('utf-8'))
conn.send(b'Hello, client!')  # Ответ клиенту

conn.close()
s.close()
  

Простой TCP-клиент

  import socket

# Создание сокета
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.1.10', 8080))  # Подключение к серверу

# Отправка и приём данных
s.send(b'Hello, server!')
data = s.recv(1024)
print('Ответ от сервера:', data.decode('utf-8'))

s.close()
  

Простой UDP-сервер

  import socket

# Создание UDP-сокета
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('0.0.0.0', 8080))  # Привязываем к адресу и порту

print('UDP сервер запущен...')
while True:
    data, addr = s.recvfrom(1024)
    print('Сообщение от', addr, ':', data.decode('utf-8'))
    s.sendto(b'Hello from server!', addr)  # Ответ отправителю
  

Простой UDP-клиент

  import socket

# Создание UDP-сокета
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Отправка сообщения
s.sendto(b'Hello, UDP Server!', ('192.168.1.10', 8080))
data, addr = s.recvfrom(1024)
print('Ответ от сервера:', data.decode('utf-8'))

s.close()