Text Size

Принципы приема и передачи пакетов

И так, как выглядят стандартная схема передачи пакетов?

Чтобы передать несколько значений, например, уровень игрока (целое число), его состояние (активен или нет), и ник (строка), обычно передают пары ключ-значение. Некоторые системы дополнительно передают тип каждого значения. Ко всему этому еще добавляют длину пакета, время отправки и номер (который абсолютно не нужен для TCP соединений!).

Т.е. для приведенного выше примера будет передано что-то вроде этого:
(номер пакета)(время отправки)
(столько-то байт впереди используется) (длина ключа=7 байт) «уровень»=(тип int)(значение)
(столько-то байт впереди используется) (7) «активен»=(тип bool)(значение)
(столько-то байт впереди используется) (3) «ник»=(тип string)(количество символов)(значение)

Вместо скобок подставьте значение, указанное внутри.

А ведь можно передать только int (4 байта), bool (1 байт) и string (длина строки + сама строка), а на другом конце линии прочитать эти данные в том же порядке. Ведь заранее известно, что именно уровень, активность, и ник мы будем принимать в следующий момент, так почему бы не использовать эту информацию!

Выше я «упустил» одну деталь: по умолчанию, в FGS типы int, uint, long и ulong (соответствуют типам C#) кодируются в 7-битном виде, что еще больше сокращает размер передаваемых данных. Т.е. uint-значение < 128 займет только 1 байт (а значение до 16384 – 2 байта). С другой стороны, максимальное значение uint.MaxValue займет уже не 4, а 5 байт. Но необходимость передавать такие большие числа возникает довольно редко.

Именно этот подход, при котором передаются только действительно необходимые данные,  предлагает использовать FGS.

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

Программа, которая отправляет данные, записывает информацию в определенной последовательности. В той же последовательности данные считываются. Таким образом, вместо передачи лишней информации - названий параметров, длины пакета и т.п. – данные доставляются максимально экономным способом.

Сама собой решается проблема «распадания» пакетов (напомню, что при передаче TCP пакетов они могут быть разбиты на несколько частей). Со стороны программиста не требуется специально обрабатывать этот момент. При попытке чтения недостающих данных (получена только часть пакета), генерируется исключение EndOfStreamException, сигнализирующее о том, что больше данных для чтения нет. В этом случае управление возвращается ядру FGS, которое вернет указатель позиции чтения данных в начало пакета. При следующем получении данных, они будут дописаны в конец буфера, после чего пакет будет обрабатываться сначала.

Поэтому при использовании FGS следует придерживаться схемы «сначала чтение – потом использование». Перед тем, как совершить какое-либо действие на основе принятых данных, дочитайте пакет до конца – возможно, не весь пакет принят.

Если Вы используете конструкцию try-catch при чтении пакета, для корректной работы системы все перехваченные исключения EndOfStreamException должны быть вызваны заново с помощью оператора throw. Исключение из этого правила: при использовании дополнительных потоков (streams), ваш код должен самостоятельно обрабатывать EndOfStreamException, которые он генерирует.

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

  1. Получение части пакета. Дописывание в буфер. Установка указателя в начало буфера.
  2. Обработка
  3. EndOfStreamException. Переход на пункт 1.
  4. Получение второй части
  5. Обработка от начала пакета
  6. Очистка буфера

И так, подведем итоги:

  • Данные следует читать в том же порядке, в котором они были переданы
  • Перед использованием полученных данных – прочитайте их до конца
  • Исключения EndOfStreamException, полученные при чтении данных пакета, перехватывать нельзя. Если это необходимо, вызовите исключение снова оператором throw.
  • Исключения EndOfStreamException, которые генерирует ваш код, следует обрабатывать внутри события получения данных. Использовать throw не нужно.


Описанные здесь принципы в большинстве своем имеют отношение к реализации собственного протокола. При использовании ObjectsNetworkingModel возникновение EndOfStreamException при ручной синхронизации сигнализирует о неправильном использовании синхронизации (другой порядок данных или попытка считать данные, которые не были записаны).

Комментарии  

 
#2 profile 02.11.2018 12:40
Need cheap hosting? Try webhosting1st, just $10 for an year.

Цитировать
 
 
#1 profile 02.11.2018 12:08
Need cheap hosting? Try webhosting1st, just $10 for an year.

Цитировать
 

Добавить комментарий


Защитный код
Обновить

Тестовая версия

СКАЧАТЬ БЕСПЛАТНО

Тестирование началось!

Пришло время испытать движок.

Пишите Ваши предложения, найденные ошибки и feedback на Этот адрес электронной почты защищен от спам-ботов. У вас должен быть включен JavaScript для просмотра. или в Skype (vbprogr).

Документацию вы найдете на этом сайте.