Quais são as melhores maneiras de serializar e desserializar mensagens de rede para jogos com vários jogadores em C / C ++?


11

Estamos usando JSON agora e queremos passar para um formato binário para alguns tipos de mensagens entre cliente e servidor.

Devo apenas ler estruturas no soquete? Use tampões proticol / parcimônia?

Como devo representar matrizes de dados?

Como deve ser a interface para empacotar / descompactar dados?

Respostas:


12

Assumindo ...

  1. você está falando sobre a conversão para um buffer de bytes
  2. Você está usando UDP e o desempenho é uma preocupação

Tente evitar desperdiçar espaço no seu pacote para definir a estrutura. O IE envia, no mínimo, um byte para indicar o tipo de pacote e, em seguida, basta assumir que cada pacote recebido segue a estrutura predefinida para esse tipo de pacote

Devo apenas ler estruturas no soquete? Use tampões proticol / parcimônia?

  • Sim, leia toda a estrutura SE VOCÊ PRECISA de toda a estrutura
  • Não, faça você mesmo a estrutura do pacote. Isso certamente será menor que a serialização usando esses métodos; você deve saber exatamente quais dados o pacote deve incluir

Como devo representar matrizes de dados?

  • Como matrizes de dados. Ao receber, continue lendo o buffer até o final dos dados para evitar o envio de uma contagem dos elementos da matriz

Como deve ser a interface para empacotar / descompactar dados?

  • Você pode configurar facilmente vários métodos para converter tipos básicos em bytes, a partir daí, desenvolver esses métodos para converter tipos personalizados também. Os detalhes sobre como fazer isso podem ser encontrados em quase qualquer lugar, tenho certeza (eu uso o C # pessoalmente)

Uma última coisa, o tamanho do pacote é uma preocupação, especialmente para um instantâneo: size = packetSize x entidades x connectedPlayers; Portanto, você pode ter 60 x 10 x 16 = 9.600 bytes por pacote. Em seguida, enviá-lo 20 vezes por segundo: = 192.000 bps = 187 KBps. Esta é obviamente uma alta velocidade de upload de banda. Daí a necessidade de minimizar cada um dos fatores que contribuem para o tamanho do pacote, sempre que possível.

Este artigo me ajudou imensamente: Rede de múltiplos jogadores da Valve


Outro artigo que descobri ao ler várias perguntas sobre serialização de objetos e redes aqui algumas semanas atrás foi este que descreve como o mecanismo da Unreal faz isso. Um bom ponto de comparação para a fonte da Valve.
Martin Foot

1
Seu método de matriz não funcionará no caso geral - onde está o 'fim dos dados'? Mesmo que suas mensagens sejam delimitadas, isso significa que você não pode ter mais de 1 array por estrutura. Para corrigir isso, o pôster original pode ficar com matrizes de comprimento fixo ou garantir que haja apenas 1 matriz por estrutura (no final da estrutura) ou enviar um valor de contagem no início da matriz.
Kylotan

Apenas mais uma dica: lembre-se de tratar endianess, isso pode ser muito irritante se você não souber que isso existe.

Bom ponto @Kylotan, concorda que em certos casos esses dados extras não podem ser evitados; mas se eu me encontrar adicionando várias matrizes a um único pacote, consideraria o envio de vários pacotes
fato005

1

Este problema foi resolvido pelo Google e Facebook:

  1. Buffers de protocolo do Google - O Google é um grande usuário de C ++:

    Os buffers de protocolo são uma maneira de codificar dados estruturados em um formato eficiente e extensível. O Google usa buffers de protocolo para quase todos os protocolos RPC internos e formatos de arquivo.

  2. Apache Thrift (anteriormente pelo Facebook):

    Thrift é uma estrutura de software para o desenvolvimento de serviços escaláveis ​​em vários idiomas. Ele combina uma pilha de software com um mecanismo de geração de código para criar serviços que funcionam de maneira eficiente e contínua entre C ++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C #, Cacau, JavaScript, Node.js, Smalltalk e OCaml.


Os buffers de protocolo do Google são muito lentos para jogos em larga escala e em tempo real. Eu os achei bastante agradáveis ​​para prototipagem e números menores de jogadores por causa do versionamento. Como sempre, seu criador de perfil contará a história real.
Patrick Hughes

Bem, eles são bons o suficiente para o Google, e o Google escala muito bem e funcionou bem quando eu os usei. Por isso eu os recomendei.
um nerd pago

O Google não requer desempenho em tempo real. O Google exige confiabilidade e tempo de atividade, ambos bem servidos pelos buffers de protocolo. A complexidade de toda essa versão de fallback e geração de código padrão acrescenta sobrecarga e, quando você está enviando e recebendo 1000 atualizações em intervalos de 50 a 100 ms, ele aumenta. Perfile um buffer de protocolo com várias versões antigas em um serializador codificado específico para os dados disponíveis. @ De fato005 tem a essência disso.
Patrick Hughes

+1, porque, embora esses formatos sejam um pouco grandes e lentos demais para a maioria dos jogos em tempo real ou de alta largura de banda (devido a conter informações extras que permitem a reconstrução de pacotes arbitrariamente complexos), isso não significa que eles não sejam úteis em alguns jogos, por exemplo. por turnos. Se a otimização de todos os recursos não for necessária, esses formatos podem economizar muito tempo e certamente são mais eficientes que o JSON.
Kylotan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.