Jakie są najlepsze sposoby serializacji i odserializowania komunikatów sieciowych w grze wieloosobowej C / C ++?

11

Obecnie używamy JSON i chcemy przejść do formatu binarnego dla niektórych typów komunikatów między klientem a serwerem.

Czy powinienem po prostu czytać struktury w gnieździe? Używać buforów / oszczędzania Proticol?

Jak mam reprezentować tablice danych?

Jak powinien wyglądać interfejs do pakowania / rozpakowywania danych?

HaltingState
źródło

Odpowiedzi:

12

Zarozumiały...

  1. mówisz o konwersji na bufor bajtów
  2. Używasz UDP, a wydajność jest problemem

Staraj się unikać marnowania miejsca w pakiecie na definiowanie struktury. IE wysyła co najmniej bajt oznaczający typ pakietu, a następnie zakłada, że ​​każdy odebrany pakiet ma zdefiniowaną strukturę dla tego typu pakietu

Czy powinienem po prostu czytać struktury w gnieździe? Używać buforów / oszczędzania Proticol?

  • Tak, przeczytaj całą strukturę JEŚLI POTRZEBUJESZ całej struktury
  • Nie, sam stwórz strukturę pakietu. To z pewnością będzie mniejsze niż serializacja przy użyciu tych metod; powinieneś dokładnie wiedzieć, jakie dane powinien zawierać pakiet

Jak mam reprezentować tablice danych?

  • Jako tablice danych. Po otrzymaniu kontynuuj odczytywanie bufora do końca danych, aby uniknąć wysyłania liczby elementów tablicy

Jak powinien wyglądać interfejs do pakowania / rozpakowywania danych?

  • Możesz łatwo skonfigurować kilka metod konwersji podstawowych typów na bajty, a następnie zbudować te metody, aby przekonwertować również typy niestandardowe. Szczegóły, jak to zrobić, można znaleźć prawie wszędzie, jestem pewien (używam C # osobiście)

I ostatnia rzecz, rozmiar pakietu jest problemem, szczególnie w przypadku migawki: size = packetSize x byty x connectedPlayers; Więc możesz mieć 60 x 10 x 16 = 9600 bajtów w pakiecie Następnie wysyłanie tego 20 razy na sekundę: = 192 000 bps = 187 KBps. Jest to oczywiście duża prędkość przesyłania. Zatem potrzeba zminimalizowania każdego z czynników przyczyniających się do wielkości pakietu tam, gdzie to możliwe.

Ten artykuł ogromnie mi pomógł: Valve Multiplayer Networking

faktycznie 005
źródło
Kolejnym artykułem, który odkryłem podczas czytania różnych pytań dotyczących szeregowania obiektów i tworzenia sieci kilka tygodni temu, był ten, który opisuje, jak robi to silnik Unreal. Dobry punkt porównania dla źródła Valve.
Martin Foot
1
Twoja metoda tablicowa nie zadziała w ogólnym przypadku - gdzie jest „koniec danych”? Nawet jeśli twoje wiadomości są rozdzielone, oznacza to, że nie możesz mieć więcej niż 1 tablicę na strukturę. Aby to naprawić, oryginalny plakat może albo trzymać się tablic o stałej długości, albo upewnić się, że jest tylko 1 tablica na strukturę (na końcu struktury), lub wysłać wartość zliczania na początku tablicy.
Kylotan
Jeszcze jedna wskazówka: pamiętaj o leczeniu endianizmu, może to być bardzo denerwujące, jeśli nie wiesz, że coś takiego istnieje.
Dobra uwaga @Kylotan, zgadzam się, że w niektórych przypadkach nie można uniknąć tych dodatkowych danych; ale jeśli znajdę się w dodawaniu wielu tablic do jednego pakietu, rozważam wysłanie wielu pakietów zamiast tego
rzeczywiście 005
1

Ten problem został rozwiązany przez Google i Facebook:

  1. Bufory protokołów Google - Google jest dużym użytkownikiem C ++:

    Bufory protokołów są sposobem kodowania danych strukturalnych w wydajnym, ale rozszerzalnym formacie. Google używa buforów protokołów do prawie wszystkich wewnętrznych protokołów RPC i formatów plików.

  2. Apache Thrift (wcześniej Facebook):

    Thrift to platforma programowa do skalowalnego rozwoju usług międzyjęzykowych. Łączy stos oprogramowania z silnikiem generowania kodu, aby tworzyć usługi, które działają wydajnie i bezproblemowo między C ++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C #, Cocoa, JavaScript, Node.js, Smalltalk i OCaml.

opłacony kujon
źródło
Bufory protokołu Google są zbyt wolne dla gier na większą skalę w czasie rzeczywistym. Uważam je jednak za całkiem miłe przy tworzeniu prototypów i mniejszej liczbie graczy ze względu na wersję. Jak zwykle Twój profiler opowie prawdziwą historię.
Patrick Hughes,
Cóż, są wystarczająco dobre dla Google, a Google skaluje się całkiem dobrze i działały dobrze, gdy ich używałem. Dlatego ich poleciłem.
opłacony frajer
Google nie wymaga działania w czasie rzeczywistym. Google wymaga niezawodności i czasu działania, które są dobrze obsługiwane przez bufory protokołów. Złożoność całej rezerwowej wersji i generowania kodu generuje dodatkowe koszty, a gdy wysyłasz i otrzymujesz 1000 aktualizacji w odstępach 50-100 ms, sumuje się. Profiluj bufor kilku protokołów w stosunku do zakodowanego serializatora specyficznego dla danych. @ rzeczywiście ma sedno.
Patrick Hughes,
+1, ponieważ chociaż te formaty są nieco zbyt duże i wolne dla większości gier w czasie rzeczywistym lub o dużej przepustowości (ze względu na dodatkowe informacje, które pozwalają na rekonstrukcję dowolnie złożonych pakietów), to nie znaczy, że nie są przydatne w niektóre gry, np. turowe. Jeśli optymalizacja każdego zasobu nie jest konieczna, te formaty mogą zaoszczędzić dużo czasu, a na pewno są bardziej wydajne niż JSON.
Kylotan