Python — Сокеты

Почему Python?

  • Можно быстро реализовать задуманную задачу.
  • Много готовых библиотек, максимально упрощающих код.

Сегодня мы научимся работать с библиотекой socket.

Импортируем библиотеку.

import socket

Создание сокета.

Создадим объект с сокетом и введем три аргумента:

Domain:

  • AF_INET — для сетевого протокола IPv4.
  • AF_INET6 — для IPv6.
  • AF_UNIX — для локальных сокетов (используя файл).

Type:

  • SOCK_STREAM — надёжная потокоориентированная служба (сервис) или потоковый сокет.
  • SOCK_DRAM — служба датаграмм или датаграммный сокет.
  • SOCK_RAW — сырой протокол поверх сетевого уровня.

Protocol:

  • IPPROTO_TCP — tcp протокол.
  • IPPROTO_UDP — udp протокол.

Допускается значение protocol = 0 (протокол не указан), в этом случае используется протокол по умолчанию.

В этой статье мы будем использовать AF_INET, SOCK_STREAM, IPROTO_TCP(0).

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)

Но AF_INET, SOCK_STREM и IPPROTO_TCP используется по умолчанию, по этому можно просто писать:

s = socket.socket()

Дальше есть два разветвления:

Сервер:

Скажем сокету подготовиться слушать порт 4444 (хост оставляем пустым, что бы сервер был доступен со всех интерфейсов):

s.bind(('', 4444))

Начинаем слушать, указав максимальное количество подключений в очереди:

s.listen(1)

Теперь нужно принять подключение.

Метод accept возвратит новое подключение, с которым мы будем работать и адрес клиента (ip, port).

conn, addr = s.accept()

Теперь мы можем общаться с клиентом через новый объект (расскажу позже).

Клиент:

Попытаемся подклбчиться к хосту itassasin.ru по порту 80:

s.connect(('itassainfil.ru', 80))

Все! Мы можем общаться с подключенным сервером.

Работа с подключенным клиентом/сервером.

s.send(bytes)

Для того, что бы отправить данные, нужно прописать метод send() и указать отправляемые данные (данные должны быть закодированны). Отправлять большие данные разом, я не рекомендую, отправляйте, к примеру, по килобайту.

s.recv(buffersize)

Для того, что бы принять данные нужно вызвать метод recv() указав размер буфера (размер принимаемой информации). Этот метод возвращает принятые, закодированные данные.

s.close()

Закрытие сокета.

Дополнительные методы.

s.settimeout(sec)

Установка максимального времени ожидания данных (recv)/коннекта, в случае чего вызовитcя исключение.

s.getsockname()

Получить адрес сокета.

s.getpeername()

Получить адрес собеседника.

s.setblocking(flag)

Установить ожидание входящих сообщений (recv). По умолчанию — true. При false, recv будет сразу же возвращать накопленные в буфере данные, даже если их нет.

Примеры.

Коннект к сайту itassasin, отправка сообщения ‘test‘ и прием ответа:

Создание сервера на порту 4444, вывод адреса подключенного клиента и примем сообщения:

Создание параллельных подключений с помощью библиотеки threading:

Я рекомендую использовать мою библиотеку MultiLib и классы SocketClient и SocketServer для создания сервера/клиента (Они совместимы только друг с другом) и помните о последовательности отправки!