Como escrever um jogo em rede? [fechadas]

73

Baseado em Por que é tão difícil desenvolver um MMO? :

O desenvolvimento de jogos em rede não é trivial; existem grandes obstáculos a serem superados não apenas na latência, mas também na prevenção de trapaças, gerenciamento de estado e balanceamento de carga. Se você não tem experiência em escrever um jogo em rede, este será um exercício de aprendizado difícil.

Conheço a teoria sobre soquetes, servidores, clientes, protocolos, conexões e outras coisas.

Agora eu me pergunto como alguém pode aprender a escrever um jogo em rede:

  • Como equilibrar problemas de carga?
  • Como gerenciar o estado do jogo?
  • Como manter as coisas sincronizadas?
  • Como proteger a comunicação e o cliente da engenharia reversa?
  • Como solucionar problemas de latência?
  • Quais itens devem ser computados localmente e quais itens no servidor?
  • ...

Existem bons livros, tutoriais, sites, artigos interessantes ou outras perguntas sobre isso?

Estou procurando respostas amplas, mas respostas específicas também são boas para aprender a diferença.

Tamara Wijsman
fonte
4
Sim, existem livros, tutoriais, sites, artigos interessantes e outras perguntas sobre isso.
Ricket
2
Eu adicionei recompensa para empurrar a pergunta sem modificá-la e dar aos usuários uma razão para responder, pois essa pergunta merece respostas, assim o melhor respondedor ganha reputação por seu trabalho, mas não há uma resposta única que responda à pergunta.
Tamara Wijsman

Respostas:

61

Além do artigo vinculado em outras respostas, posso contar um pouco sobre a experiência do Projeto Arianne .

Como manter as coisas sincronizadas?

Nós construímos o framework " Marauroa " em torno do conceito de ações e percepções: as ações são enviadas do cliente para o servidor carregando informações do usuário (caminhe para a esquerda, ataque os monstros nº 47, diga 'olá'). E as percepções são enviadas do servidor para os clientes, informando sobre o estado do mundo ao seu redor. Essas percepções são enviadas a cada turno. Dependendo do jogo, usamos tempos de rotação de 30ms a 300ms.

Temos dois tipos de percepções : Uma percepção completa é enviada no login e quando o jogador entra em uma nova área (zona). Depois disso, as percepções diferenciais são enviadas, incluindo apenas os atributos modificados (por exemplo, posição) dos objetos modificados e, é claro, objetos novos e removidos.

Como solucionar problemas de latência?

Acreditamos firmemente que "o servidor está sempre certo". O cliente faz algumas previsões, como andar tranqüilo, verificações de colisões e assim por diante. Mas se um cliente e o servidor discordam de algo, o servidor vence. O subprojeto Stendhal (um RPG 2D) usa um tempo de rotação de 300ms por padrão (com bastante suavização do lado do cliente). Isso torna Stendhal muito resistente a lag.

Nota: Alguns outros jogos confiam no cliente até certo ponto para minimizar o impacto do atraso na rede. No WoW, era frequentemente explorado em um campo de batalha chamado "Warsong Gulch". Existem duas maneiras pelas quais um jogador com a bandeira pode escolher: no meio, através de um túnel, e uma à vista, subindo a colina. Assim, um trapaceiro corre em direção ao túnel e causa lentidão para si mesmo. O servidor e os outros clientes continuarão vendo ele correndo em direção a ele. Mas, após algum tempo, esse cliente pode dizer ao servidor que foi em direção à colina. O WoW verificará se a distância entre as últimas coordenadas transmitidas e as atuais se encaixa no segmento de tempo e aceita isso.

Uso de UDP vs. TCP

Nas versões anteriores, usamos o UDP para reduzir a sobrecarga do TCP. Lidamos com pacotes perdidos por conta própria. Isso funcionou perfeitamente nos primeiros dias do projeto. Mas quando o servidor foi transferido de uma conexão DSL doméstica para um data center real há vários anos, tivemos grandes problemas. O UDP é (ou pelo menos há 5 anos atrás) extremamente exigente no poder da CPU do hardware do firewall: O conjunto de regras deve ser aplicado a todos os pacotes UDP. Para o TCP, no entanto, o conjunto de regras é aplicado apenas aos 3 primeiros pacotes. Depois disso, a conexão é estabelecida. Todos os pacotes a seguir ignoram o conjunto de regras normal porque estão na tabela de rastreamento de conexão ou porque não possuem um sinalizador SYN.

Como proteger a comunicação e o cliente da engenharia reversa?

Arianne é completamente de código aberto, incluindo cliente, servidor, gráficos, música. E é claro que isso inclui nossa documentação de protocolo e até um analisador usado para depuração.

É fácil proteger a comunicação contra sniffing não autorizado por terceiros usando SSL.

É, no entanto, impossível protegê-lo contra a engenharia reversa. Claro que você pode ofuscá-lo e usar técnicas anti-depuração. Mas, no final, você não pode impedir a engenharia reversa de software que você distribui aos usuários. Há uma apresentação muito interessante sobre como o Skype foi revertido, apesar de os desenvolvedores terem se esforçado muito em técnicas de anti-depuração: http://recon.cx/en/f/vskype-part1.pdf

Nota: Em alguns países, a engenharia reversa é ilegal ou permite a inclusão de um parágrafo na licença ou o ToS não permite a engenharia reversa. Mas há outros países (como o que eu moro) que permitem explicitamente a engenharia reversa no contexto do desenvolvimento de formatos compatíveis de armazenamento de dados ou protocolos de transmissão, parágrafos da licença ou ToS tentando impedir que sejam nulos. (Tudo nesta seção é, até onde eu sei, não sou advogado)

Quais itens devem ser computados localmente e quais itens no servidor?

Computamos tudo relacionado à lógica do jogo no servidor. O cliente irá prever determinados eventos para que o jogo seja tranquilo. Mas no final, o servidor está sempre certo.

Eventos previstos são, por exemplo, parada de movimento quando uma colisão é atingida. Stendhal usa uma grade para posicionar elementos. E do ponto de vista do servidor, o canto superior esquerdo de cada entidade fica exatamente em um quadrado. Mas o cliente irá movê-los sem problemas entre os ladrilhos. Ele também desenhará o pseudo efeito 3d. Portanto, uma entidade que possui uma base de 1x1 pode ser maior no cliente.

Como equilibrar problemas de carga?

Tente manter isso o mais simples possível, para facilitar a manutenção.

O balanceamento de carga de conteúdo estático é bem conhecido na área de clusters de servidores http e redes de distribuição de conteúdo.

Um conceito bastante simples para o balanceamento de carga dos serviços de jogos é dividir servidores entre regiões / zonas. Portanto, a zona AC está em um servidor e as zonas DF estão em outro. Isso é especialmente fácil se você não pode procurar zonas de um conjunto para zonas de outro conjunto. Você precisa fazer algumas verificações lá para que um cliente possa se conectar apenas a um servidor de zona responsável pela zona em que o jogador está.

A maneira mais fácil de transferir jogadores de um servidor para outro é gravá-los no banco de dados, dizer ao cliente para conectar-se ao outro servidor de zona e desconectá-los do atual. O cliente se conectará ao novo servidor de zona que o carregará do banco de dados. (Como você precisa carregar de / armazenar no código do banco de dados, a comunicação direta entre os servidores para entrega pode ser implementada posteriormente).

Alguns serviços globais adicionais são necessários por meio de: No login, os clientes precisam ser informados para se conectarem ao servidor de zona correto. E você pode querer um sistema de bate-papo mundial.

Entrei em detalhes sobre este tópico em Como o balanceamento de carga é alcançado nos MMOs?

Hendrik Brummermann
fonte
11
Você mencionou que o UDP requer um pouco mais de CPU, mas não mencionou que o TCP requer pelo menos três viagens entre o cliente e o servidor antes do processamento do pacote E os pacotes são armazenados em buffer até que todos os pacotes anteriores tenham sido recebidos, o que significa que você pode ser ridículo quantidades de atraso aguardando pacotes que não são mais relevantes. Parece uma coisa importante a mencionar.
BlueRaja - Danny Pflughoeft
2
@ Danny, são necessários três pacotes para iniciar uma nova conexão TCP: cliente para servidor: SYN, servidor para cliente: SYN ACK, cliente para servidor: ACK + dados. Essa é uma viagem de ida e volta mais que o UDP, mas só acontece no início quando o cliente entra em contato com o servidor pela primeira vez. Em uma conexão estabelecida, todos os pacotes são processados ​​imediatamente, sem viagens adicionais. Haverá uma resposta ACK, mas os dados recebidos já serão processados ​​enquanto os pacotes ACK retornam.
Hendrik Brummermann
11
@ Danny, o TCP lida com a perda de pacotes automaticamente e de uma maneira bastante eficiente. É difícil reimplementar você mesmo usando o UDP; a menos que seu protocolo esteja correto com pacotes aleatórios não entregues. O próximo problema é que o TCP garante que a ordem dos pacotes, enquanto os pacotes UDP possam ser recebidos na ordem errada. Novamente, é difícil reimplementá-lo, a menos que você possa simplesmente ignorar pacotes mais antigos, por exemplo, com base em um contador de pacotes. Se um tempo de resposta muito curto for necessário para o TCP, o algoritmo do Nagle precisará ser desativado.
Hendrik Brummermann
Parece que você defendeu veementemente sua posição sem abordar a questão muito real do atraso do TCP. Talvez o verdadeiro problema é a sua escolha de um firewall em vez de um protocolo resistente DDoS hardware
MickLH
27

http://gafferongames.com/networking-for-game-programmers/

É um ótimo conjunto de artigos sobre vários problemas e soluções que lidam com redes de jogos.

jsimmons
fonte
11
+1, mas não confie neles cegamente. De acordo com minha experiência, por exemplo, não é uma boa idéia usar o UDP e reinventar o recurso do TCP. O UPD é útil apenas se os pacotes perdidos não tiverem nenhum impacto, ou seja, todo pacote UDP contém o estado relevante completo do mundo. O WoW usa TCP, SL está em andamento na mudança de UDP para TCP (até HTTP para conteúdo estático) e melhorou significativamente o desempenho com essas alterações.
Hendrik Brummermann 31/07
7
Você não está reinventando os recursos do TCP, nem todos eles, pelo menos. O controle de fluxo TCP e a semântica da perda de pacotes são terríveis para um jogo que requer uma conexão de baixa latência. O TCP só é útil se você não se importa com a latência ou com a minimização da largura de banda necessária.
Jsimmons
2
Second Life massivamente melhor desempenho, indo de UDP para HTTP sobre TCP: blogs.secondlife.com/community/technology/blog/2010/08/13/...
Hendrik Brummermann
5
Na verdade, eles melhoraram o desempenho do fluxo de ativos alterando a forma como ele funciona. O uso de HTTP / TCP nessa instância facilitou a implementação, não mais rápido. Também devo observar que o zeromq é um projeto interessante e pode ser muito bem dimensionado para redes de jogos. zeromq.org
jsimmons
8

Dependendo do tipo de jogo que você está escrevendo, você pode evitar parte da programação de rede de baixo nível. Alguns tipos de jogos não exigem muita comunicação entre os clientes e o servidor. Nesses casos, pode-se optar por usar uma estrutura de nível superior. Por exemplo, estou desenvolvendo um jogo de estratégia baseado em turnos em C # / .NET. Os jogos de estratégia baseados em turnos são um tanto únicos, pois a grande maioria da comunicação cliente / servidor ocorre no início e no final de um turno, com relativamente pouco no meio. Portanto, optei por usar o Windows Communication Foundation (WCF), uma estrutura de comunicação de alto nível projetada principalmente para serviços da web. Em vez de trabalhar diretamente com soquetes e toda essa bobagem de rede de baixo nível, posso fazer o que parecem ser chamadas de método padrão, e deixe o WCF lidar com o protocolo e as camadas de transporte para mim. A única vez que tive que lidar com o material de rede de baixo nível foi quando configurei meus endpoints, o que é praticamente uma transação única em um arquivo de configuração. Ainda pode ser necessário implementar alguma lógica de serialização personalizada, mas você precisa fazer esse tipo de coisa independentemente.

Mike Strobel
fonte
8

A questão é muito ampla. As respostas podem preencher um site por conta própria. Mas há livros que abordam isso, principalmente esses dois:

Observe que mesmo esses livros não são um guia completo, mas uma coleção de idéias e abordagens que você pode usar, algumas das quais não funcionam juntas ou são contraditórias. Normalmente, assume alguma experiência no desenvolvimento de jogos, aplicativos de rede ou, idealmente, ambos.

(Observe que estou falando mais sobre os MMOs na pergunta original - um 'jogo em rede' pode significar todo tipo de coisa, desde um jogo de texto baseado em PHP até um MMO, e as sub-perguntas acima não são todas aplicar a cada tipo.)

Kylotan
fonte
7

Como equilibrar problemas de carga?

tamanho geográfico fixo + várias instâncias é a solução mais fácil. Os caras que trabalhavam no SWG experimentaram o tamanho dinâmico e se arrependeram.

Como gerenciar o estado do jogo?

O servidor é autoritário.

Como manter as coisas sincronizadas?

Atualizações periódicas de sincronização do servidor. (não tenho certeza qual é a preocupação aqui)

Como proteger a comunicação e o cliente da engenharia reversa?

Impossível. apenas verifique se não confia em nada que recebe do cliente e se o servidor é autorizado.

Como solucionar problemas de latência?

Isso vai muito longe, mas superficialmente você executa a mesma simulação no cliente que o servidor e, quando a sincronização acontece, corrige as coisas. Todas as decisões tomadas no cliente também são simuladas no servidor, portanto pode haver más decisões, mas geralmente as coisas dão certo.

Quais itens devem ser computados localmente e quais itens no servidor?

Pense no cliente como executando um sim não autoritário do que está acontecendo no servidor. A capacidade de resposta é essencial para a experiência do jogador, então você precisa fazer algo toda vez que um jogador toma uma decisão, mesmo que esteja apenas começando um bar.

Verdade seja dita, muitos desses problemas são ortogonais e podem ter soluções aplicadas mais tarde. Comece a jogar e não se preocupe muito com essas coisas.

Aaron Brady
fonte
4

Esta questão é muito ampla. Também é uma área muito complicada de dominar, os programadores de rede são bastante procurados na indústria com um salário correspondente, o que meio que indica que é uma área 'não resolvida'. Existem livros por aí, sim, muitos. Existem bons livros por aí, sem dúvida. Existem livros por aí que respondam às suas perguntas? ... Acho que não. Eles podem ter soluções que funcionam em algumas situações ou dicas sobre o que procurar, mas quase todas as suas perguntas dependem do jogo ... essa é uma área em que você realmente precisa trabalhar muito sozinho, é tão aparentemente trivial e pode dar errado de muitas maneiras (não controladas).

Kaj
fonte