Jogo de cartas cliente-servidor baseado em turnos - Unicast (TCP) ou Multicast (UDP)

8

Atualmente, estou planejando fazer um projeto de jogo de cartas no qual os clientes se comuniquem com o servidor de maneira síncrona e baseada em turnos usando mensagens enviadas por soquetes. O problema que tenho é como lidar com o seguinte cenário:

(O cliente dá uma guinada e envia sua ação ao servidor)

  1. O cliente envia uma mensagem informando ao servidor sua jogada no turn (por exemplo, joga o cartão 5 da mão que precisa ser colocado na mesa)

  2. O servidor recebe mensagens e atualiza o estado do jogo (o servidor manterá todo o estado do jogo).

  3. O servidor itera através de uma lista de clientes conectados e envia uma mensagem para informar sobre a mudança de estado

  4. Todos os clientes são atualizados para exibir o estado

Tudo isso se baseia no uso do TCP e, agora, parece um pouco com o padrão Observer. A razão pela qual isso parece ser um problema para mim é que essa mensagem não parece ser ponto a ponto como os outros, pois eu quero enviá-la a todos os clientes e não parece muito eficiente enviando a mesma mensagem em dessa maneira.

Eu estava pensando em usar multicast com o UDP, pois assim eu poderia enviar a mensagem para todos os clientes. No entanto, isso não significa que os clientes poderiam, em teoria, ser capazes de enviar mensagens uns aos outros? É claro que também existe o aspecto síncrono, embora isso possa ser colocado no topo do UDP, eu acho.

Basicamente, eu gostaria de saber o que seria uma boa prática, já que esse projeto realmente tem tudo a ver com aprendizado, e mesmo que não seja grande o suficiente para encontrar problemas de desempenho, eu gostaria de considerá-los de qualquer maneira.

No entanto, observe que não estou interessado em usar o middleware orientado a mensagens como uma solução (tenho experiência com o uso do MOM e estou interessado em considerar outras opções, excluindo o MOM, se os soquetes TCP forem uma má idéia!).

LDM91
fonte

Respostas:

11

Não otimize prematuramente. Mantenha simples. Usar o TCP neste caso é bom e não vejo nenhum problema com o seu esquema atual.

O UDP geralmente é usado para cenários críticos de desempenho, como em um jogo de ação online, porque permite controle explícito sobre pacotes individuais, em vez de trabalhar sobre uma abstração de camadas de fluxos como o TCP. No entanto, embora você tenha algum ganho de velocidade controlando exatamente como deseja que os dados sejam enviados, o UDP não lida com a perda de pacotes ou a solicitação de pacotes como o TCP; nesse caso, você deve codificá-lo você mesmo. Portanto, como este é um jogo de cartas baseado em turnos, duvido que você queira sacrificar a confiabilidade acima da velocidade, então use o TCP.

XiaoChuan Yu
fonte
Obrigado pela sua resposta, ficou claro e parece responder a tudo o que pedi.
LDM91 30/03/12
3

Mesmo muitos MMOs grandes e populares estão usando exclusivamente o TCP. Ele fará tudo o que você precisa com todas as características de eficiência necessárias.

O UDP requer muita complexidade extra, o multicast exige ainda mais complexidade e você não obterá nada disso. Se você está apenas interessado em aprender, faça uma demonstração técnica para si mesmo, mas não pense que o projeto em si será de alguma forma melhor por causa disso.

Se você estiver interessado em usar o UDP, sua primeira tarefa será basicamente reimplementar o TCP em cima do UDP, apenas para garantir que você realmente entenda como lidar com todos os problemas que o TCP resolve para você: congestionamento controle, retransmissão de pacotes perdidos, manuseio duplicado atrasado, pedido de pacotes, handshake de conexão confiável, sequência de desconexão confiável etc.

Não é necessariamente difícil resolver tudo isso, mas exige uma compreensão profunda da rede, do protocolo IP e de como esses problemas são resolvidos.

A partir daí, construir a biblioteca para oferecer recursos que o TCP não possui é onde a diversão realmente começa. Usando um fluxo de mensagens multiplexado sobre um fluxo de pacotes, controle de congestionamento mais eficiente, manuseio de limite de taxa, multicanais, configuração de canal (se o canal exige mensagens em ordem ou não, se pacotes descartados são permitidos etc.) e assim por diante.

Eu sugiro que você leia a seguinte série de artigos. Não é perfeito e faz algumas afirmações muito questionáveis ​​(começando com o absurdo "nunca use TCP nos jogos"), mas seus detalhes técnicos são úteis para novos programadores de rede: http://gafferongames.com/networking-for-game- programadores / udp-vs-tcp /

Sean Middleditch
fonte
11
Na introdução desse artigo, o autor afirmou: "A escolha que você faz depende inteiramente do tipo de jogo que você deseja conectar em rede. Portanto, a partir deste momento e no restante desta série de artigos, assumirei que você deseja para criar um jogo de ação em rede. Você conhece jogos como Halo, Battlefield 1942, Quake, Unreal, CounterStrke, Team Fortress e assim por diante. "
XiaoChuan Yu
Ah, eu senti falta disso quando o deslizei para ter certeza de que era tão bom quanto me lembro. Meu mal, desculpe.
quer
-1 para "Se você estiver interessado em usar o UDP, sua primeira tarefa será basicamente reimplementar o TCP sobre o UDP" , é muito errado o IMO. Muito mais útil para aprender o UDP realmente fazendo as coisas pelas quais o UDP é escolhido.
o0 '.
@ Lohoris: Isso é inútil e nem correto. Você DEVE ter a capacidade de enviar mensagens garantidas em ordem, mesmo com o UDP. Você precisa enviar mensagens não garantidas em ordem. Você precisa enviar mensagens garantidas fora de ordem. É mais simples começar com o comportamento semelhante ao TCP, porque exige a implementação de todos os recursos necessários e é mais fácil de testar, e mesmo por si só ainda oferece recursos úteis, como um controle mais direto do uso e da latência da largura de banda.
Sean Middleditch
@seanmiddleditch errado. Não há nada de errado em usar UDP e TCP no mesmo jogo, portanto você não precisa implementar uma entrega garantida por UDP.
o0 '.