Каковы лучшие способы сериализации и десериализации сетевых сообщений для многопользовательской игры C / C ++?


11

Сейчас мы используем JSON и хотим перейти на двоичный формат для некоторых типов сообщений между клиентом и сервером.

Должен ли я просто читать структуры в сокет? Использовать Proticol буферы / бережливость?

Как я должен представлять массивы данных?

Как должен выглядеть интерфейс для упаковки / распаковки данных?

Ответы:


12

Предполагая, что ...

  1. вы говорите о преобразовании в буфер байтов
  2. Вы используете UDP, и производительность является проблемой

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

Должен ли я просто читать структуры в сокет? Использовать Proticol буферы / бережливость?

  • Да, прочитайте всю структуру, если вам нужна вся структура
  • Нет, сделайте структуру пакета самостоятельно, это, безусловно, будет меньше, чем сериализация с использованием этих методов; вы должны точно знать, какие данные пакет должен включать

Как я должен представлять массивы данных?

  • Как массивы данных. При получении продолжайте чтение буфера до конца данных, чтобы избежать отправки количества элементов массива

Как должен выглядеть интерфейс для упаковки / распаковки данных?

  • Вы можете легко настроить кучу методов для преобразования базовых типов в байты, оттуда основываться на этих методах для преобразования пользовательских типов. Подробности о том, как это сделать, можно найти практически везде, я уверен (я лично использую C #)

Одна последняя вещь, размер пакета является проблемой, особенно для снимка: размер = PacketSize х субъектов х connectedPlayers; Таким образом , вы можете иметь 60 х 10 х 16 = 9600 байт на пакет затем отправить это в 20 раз в секунду: = 192000 бит в секунду = 187 Kbps. Это очевидно высокая скорость загрузки. Таким образом, необходимо минимизировать каждый из факторов, влияющих на размер пакета, где это возможно.

Эта статья мне очень помогла: Valve Multiplayer Networking


Еще одна статья, которую я обнаружил, читая здесь несколько недель назад по различным вопросам сериализации объектов и сетевым вопросам, была той, которая описывает, как это делает движок Unreal. Хорошая точка сравнения для источника Valve.
Мартин Фут

1
Ваш метод массива не будет работать в общем случае - где «конец данных»? Даже если ваши сообщения разделены, это означает, что вы не можете иметь более 1 массива на структуру. Чтобы исправить это, оригинальный плакат может либо придерживаться фиксированных массивов длины, или убедитесь , что есть только один массив в структуры (в конце структуры), или отправить значение счетчика в начале массива.
Kylotan

Еще один совет: не забывайте обращаться с порядком байтов, это может очень раздражать, если вы не знаете, что такое существует.

Хороший вопрос @Kylotan, согласитесь, что в некоторых случаях эти дополнительные данные нельзя избежать; но если я считаю себя добавление нескольких массивов в один пакет, я хотел бы рассмотреть отправку нескольких пакетов вместо
indeed005

1

Эта проблема была решена Google и Facebook:

  1. Протокол Буферы компании Google - Google является большим пользователем C ++:

    Буферы протокола - это способ кодирования структурированных данных в эффективном, но расширяемом формате. Google использует буфер протоколов почти для всех своих внутренних протоколов RPC и форматов файлов.

  2. Apache Thrift (ранее Facebook):

    Thrift - это программная структура для разработки масштабируемых кросс-языковых сервисов. Он объединяет программный стек с механизмом генерации кода для создания сервисов, которые эффективно и без проблем работают между C ++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C #, Какао, JavaScript, Node.js, Smalltalk и OCaml.


Протоколные буферы Google слишком медленные для больших игр в реальном времени. Однако я нашел их довольно хорошими для создания прототипов и меньшего количества игроков из-за версий. Как обычно, ваш профилировщик расскажет реальную историю.
Патрик Хьюз

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

Google не требует производительности в реальном времени. Google действительно требует надежности и времени работы, оба из которых хорошо обслуживаются буферами протокола. Сложность всего этого резервного управления версиями и генерации стандартного кода добавляет накладных расходов, а когда вы отправляете и получаете 1000 обновлений с интервалами 50-100 мсек, это добавляет. Профилируйте буфер протокола нескольких старых версий против закодированного сериализатора, специфичного для данных под рукой. @ действительно 005 имеет суть этого.
Патрик Хьюз

+1, потому что, хотя эти форматы слишком большие и медленные для большинства игр в реальном времени или с высокой пропускной способностью (из-за содержания дополнительной информации, позволяющей восстанавливать произвольно сложные пакеты), это не означает, что они бесполезны в некоторые игры, например. пошаговые. Если оптимизация каждого ресурса не требуется, тогда эти форматы могут сэкономить вам много времени, и они, безусловно, более эффективны, чем JSON.
Kylotan
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.