Python Безопасность Обучение

Python в ИБ. Урок 2. Пишем небольшое серверное приложение

Python в ИБ. Урок 2. Пишем небольшое серверное приложение

В этом уроке продолжаем познавать основы сетевого программирования и напишем небольшой сервер. Как вы знаете из прошлого урока, существуют сетевые клиенты и серверы, при это они используют одинаковую абстракцию под названием “сокет”. Клиенты писать мы уже умеем, сегодня научимся писать сервера.

Теория.

Большая часть теории есть в предыдущем уроке, необходимо с ней ознакомиться, а также самостоятельно почитать про сокеты и основые сетевого взаимодействия, чтобы лучше представлять происходящее.

Рассмотрим небольшую теорию для сервера, скорее это будет просто кратким описанием того, что из себя представляет сервер.

По сути сервер представляет собой некоторое приложение, к которому могут подключаться клиенты и взаимодействовать с ним по определённому протоколу.

Сервера классифицируются по различным признакам, например по количеству соединений, бывают однопоточные (поддерживается только одно соединение для одного клиента, и пока он не закончит взаимодействие, никто не может подключиться) и многопоточные (поддерживается множество соединений для множества клиентов, понятное дело, что в итоге у каждого клиента соединение одно и своё, но клиентов может быть много).

Наверное объяснение довольно громоздкое, попытаемся свести это в короткие тезисы.

Однопоточный сервер – принимает только одного клиента и обслуживает его, при этом остальные клиенты ждут, т.к. возможно только одно подключение.

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

Клиенты осуществляют подключение через порт (известно из прошлого урока), а сервер “слушает” этот порт и ждёт подключений. Когда подключение происходит сервер создаёт сокет, с помощью которого может общаться с клиентом.

Для того, чтобы поместить сервер на определённый порт используется операция “bind”, которая открыает слущающий порт и предоставляет его серверу. Если требуемый порт занят, то эта операция будет неудачно и сервер не будет запущен.

Если вам нужные ещё теоретические сведения, вы можете поискать их самостоятельно, а мы переходим к практике.

Практика.

Итак, мы реализуем простой однопоточный сервер, который будет принимать подключение клиента и например выводить текущее время, после чего закрывать соединение. То есть мы реализуем сервер-времени (можете почитать про NTP-сервера и поймёте, что такие сервера активно используются).

Для начала импортируем библиотеки, который нам понадобятся.

С библиотекой “socket” мы уже знакомы, библиотека “time” будет нужна нам для вывода времени, а библиотека “sys” поможет передвать номер порта динамически, то есть в консоли перед запуском программы (будет показано позже).

Теперь напишем код для обработки запуска из консоли нашего сервера.

В переменную port будет помещён аргумент командой строки при запуске нашего сервера, если аргумента не будет, то выведется сообщение о том, как надо использовать данный скрипт. Продемонстрируем это на примере.

При вводе числа, оно будет сохранено в переменную порт.

Такая конструкция нужна для того, чтобы иметь возможность открывать сервер на любом желаемом порту без залезания в исходники и исправления жёстко заданного номера порта.

Теперь напишем код для создания серверного сокета, его bind’a на определённый порт и перевод в “слущающее” состояние.

Обратите внимание на переменную host и её содержимое. Такой ip-адрес означает, что сервер будет доступен на всех сетевых интерфейсах компьютера (то есть если вы подключены по Ethernet и Wi-Fi и имеет 2 разных ip-адреса в этих сетях, то в каждой сети будет доступ к этому серверу по вашему ip-адресу), по другому можно сказать, что сервер открывается на все интерфейсы и к нему может подключится любой пользователь сети в которой вы находитесь.

Серверный сокет создаётся уже знакомым нам методом, bind’инг происходит также как и подключение, а метод listen, выводит сервер в слущающее состояние. Аргумент в методе listen означает максимально количество соединений в очереди (то есть если сервер занят обработкой клиента, сколько может быть ждущих соединений).

Теперь нужно написать обработку подключений.

В бесконечном цикле мы ждём подключений и если подключение произошло, то мы отправляем UNIX-time и символ перевода строки, после чего закрываем соединение с данным клиентом.

Попробуем запустить наш сервер и подключится с Linux’a с помощью nc.

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

Отлично, мы написали сервер, который возвращает UNIX-время при подключении. Подумайте, как можно закрыть сервер – это интересная задачка. А данный урок подходит к концу, в следующем уроки мы разберём более удобную библиотеку для создания многопоточных серверных приложений (однопоточные редко используются на практике) и напишем серверное приложение с авторизацией.

Очень злой админ
Очень злой админ Автор статьи

Админ сайта. Публикует интересные статьи с других ресурсов, либо их переводы. Если есть настроение, бывает, что пишет и что-то своё.