Оглавление
1. Отправил и забыл
После прочтения всех предыдущих статей вам должно быть понятно, как сформировать пакет и каким образом указать куда его отправить.
И возникает вопрос: "А как же собственно отправить данные по сети?". Ответ: использовать сложные алгоритмы, придуманные до нас. Эти алгоритмы называют протоколами. Для того, чтобы ими пользоваться, нет необходимости знать, как именно они работают. Достаточно понимать их ключевые особенности.
Самый простой протокол это UDP (User Datagram Protocol). Протокол позволяет отправить пакет на указанный адрес. А также прослушивая порт получать пакеты. Он имеет некоторые особенности:
- Протокол не гарантирует, что отправленные данные дойдут до цели.
- Протокол не гарантирует, что цель ответит на полученные данные.
- Протокол не гарантирует, что цель получит данные в порядке их отправления.
- Протокол не требует установки канала связи.
Как вы можете заметить, протокол абсолютно ненадёжен. Взаимодействие по этому протоколу можно описать фразой "отправил и забыл". Но данный протокол невероятно прост и очень быстр, позволяет отправлять большие объёмы данных.
2. Для чего используется
Основное применение протокола - системы реального времени. Например: видео, игры. Системы, где отправляются огромные потоки данных, и не имеет значения, если какие-то данные не дойдут или дойдут не полностью.
Стоит отметить, что современное интернет соединение достаточно стабильно, большая часть пакетов отправляется и получается без повреждений.
3. Пример архитектуры
Данный протокол подходит для двух вещей: получение данных и отправка одиночных запросов. Рассмотрим простейшую архитектуру сервера для получения и обработки запросов.
Во-первых, протокол не гарантирует порядок доставки, поэтому сервер должен уметь обрабатывать любые запросы в любой момент времени, следовательно, он должен либо откладывать неподходящие запросы, либо всегда выполнять любые приходящие запросы. Откладывание означает запоминание запроса в некую структуру данных и последующую обработку, что может сильно замедлить работу сервера.
Во-вторых, сервер может менять своё состояние в зависимости от полученных запросов.
Из выше сказанного следует, что сервер состоит из двух частей:
- Состояние
- Цикл обработки
Цикл обработки может запрашивать текущее состояние, а также отправлять запрос на изменение. Соответственно, на схеме сервер выглядит так:
Код на питоне выглядел бы примерно так:
- state = State()
- while not state.stoped:
- try:
- data, sender = receive_socket.recvfrom(state.buffer_size)
- if not data:
- continue;
- correct(data)
- request_type = detect_type(data)
- if state.is_valid_state_for(request_type):
- response = process(request_type, data, state)
- if response != None:
- send_socket.sendto(response, sender)
- except socket.timeout as err:
- continue;
- except socket.error as err:
- print(err);
- continue;
Обратите внимание на процедуру correct. Она предназначена для проверки того, что данные, полученные из сети, не повреждены и вообще правильны, если это не так, то она должна исправить их или заменить на некую заглушку.
Данный сервер отвечает на порт и адрес отправившего запрос, что часто бывает неправильно. Поэтому рекомендуется сделать некую регистрацию. Клиент должен иметь возможность указать, на какой порт он хочет получать ответы.