Які найкращі способи серіалізації та несеріалізації мережевих повідомлень для багатокористувацької гри C / C ++?


11

Зараз ми використовуємо JSON і хочемо перейти до двійкового формату для деяких типів повідомлень між клієнтом і сервером.

Чи повинен я просто прочитати структури в сокет? Використовувати протіколові буфери / ощадливість?

Як я повинен представляти масиви даних?

Яким повинен виглядати інтерфейс для упаковки / розпакування даних?

Відповіді:


12

Припускаючи ...

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

Намагайтеся не витрачати місця в пакеті для визначення структури. IE надсилає, як мінімум, байт для позначення типу пакету, тоді просто припускають, що кожен отриманий пакет відповідає попередньо визначеній структурі для цього типу пакету

Чи повинен я просто прочитати структури в сокет? Використовувати протіколові буфери / ощадливість?

  • Так, прочитайте всю структуру ЯКЩО вам потрібна ціла структура
  • Ні, зробіть структуру пакету самостійно. Це, безумовно, буде менше, ніж серіалізація за допомогою цих методів; ви повинні точно знати, які дані повинен включати пакет

Як я повинен представляти масиви даних?

  • Як масиви даних. При отриманні продовжуйте читати буфер до кінця даних, щоб уникнути надсилання Count елементів масиву

Яким повинен виглядати інтерфейс для упаковки / розпакування даних?

  • Ви можете легко налаштувати купу методів для перетворення основних типів у байти, звідти будувати ці методи для перетворення спеціальних типів. Конкретні відомості про те, як це зробити, можна знайти майже в будь-якому місці, в якому я впевнений (я використовую C # особисто)

І останнє, що розмір пакета викликає занепокоєння, особливо для знімка: size = packetSize x сутностей x підключенняPlayers; Таким чином, у вас може бути 60 x 10 x 16 = 9 600 байт на пакет, тоді ви надсилаєте це 20 разів на секунду: = 192 000 bps = 187 KBps. Очевидно, що це висока швидкість завантаження. Таким чином, потрібно мінімізувати кожен із факторів, що сприяють розміру пакету, де це можливо.

Ця стаття мені дуже допомогла: Valve Multiplayer Networking


Ще одна стаття, яку я виявив, читаючи різні питання серіалізації об'єктів та мережевих питань тут кілька тижнів тому, була ця, в якій описано, як це робить двигун Unreal. Гарний момент порівняння для джерела Valve.
Мартін Фут

1
Ваш метод масиву не працює в загальному випадку - де "кінець даних"? Навіть якщо ваші повідомлення обмежені, це означає, що ви не можете мати більше одного масиву на структуру. Щоб виправити це, оригінальний плакат міг або дотримуватися масивів фіксованої довжини, або гарантувати, що існує лише 1 масив на структуру (в кінці структури), або надіслати значення підрахунку на початку масиву.
Kylotan

Ще одна порада: не забудьте лікувати ендіаз, це може бути дуже неприємно, якщо ви не знаєте, що таке існує.

Хороша справа @Kylotan, погоджуйтеся, що в певних випадках цих зайвих даних не уникнути; але якщо я можу додавати декілька масивів до одного пакету, я б
подумав

1

Цю проблему вирішили Google та Facebook:

  1. Буфери протоколів Google - Google є великим користувачем C ++:

    Буфери протоколів - це спосіб кодування структурованих даних у ефективному, але розширюваному форматі. Google використовує буфери протоколів майже для всіх своїх внутрішніх протоколів RPC та форматів файлів.

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

    Thrift - це програмне забезпечення для розробки масштабних мовних послуг. Він поєднує стек програмного забезпечення з механізмом генерування коду для створення служб, які ефективно і безперебійно працюють між C ++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C #, Cocoa, 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.