Juego de cartas cliente-servidor por turnos: unidifusión (TCP) o multidifusión (UDP)

8

Actualmente estoy planeando hacer un proyecto de juego de cartas donde los clientes se comunicarán con el servidor de forma sincronizada y por turnos utilizando mensajes enviados a través de sockets. El problema que tengo es cómo manejar el siguiente escenario:

(El cliente toma el turno y envía su acción al servidor)

  1. El cliente envía un mensaje diciéndole al servidor su movimiento para el turno (por ejemplo, juega la carta 5 de su mano que debe colocarse sobre la mesa)

  2. El servidor recibe mensajes y actualiza el estado del juego (el servidor contendrá todo el estado del juego).

  3. El servidor itera a través de una lista de clientes conectados y envía un mensaje para informarles sobre cambios en el estado

  4. Todos los clientes se actualizan para mostrar el estado

Todo esto se basa en el uso de TCP, y mirándolo ahora parece un poco el patrón Observador. La razón por la que esto parece ser un problema para mí es que este mensaje no parece ser punto a punto como los demás, ya que quiero enviarlo a todos los clientes, y no parece muy eficiente enviar el mismo mensaje en de esa manera.

Estaba pensando en usar la multidifusión con UDP para poder enviar el mensaje a todos los clientes, sin embargo, ¿no significa esto que los clientes en teoría podrían enviarse mensajes entre ellos? Por supuesto, también existe el aspecto síncrono, aunque supongo que esto podría colocarse sobre el UDP.

Básicamente, me gustaría saber qué sería una buena práctica, ya que este proyecto realmente se trata de aprender, y aunque no será lo suficientemente grande como para enfrentar problemas de rendimiento, me gustaría considerarlos de todos modos.

Sin embargo, tenga en cuenta que no estoy interesado en usar middleware orientado a mensajes como solución (¡Tengo experiencia con el uso de MOM y estoy interesado en considerar otras opciones que excluyan MOM si los sockets TCP son una mala idea!).

LDM91
fuente

Respuestas:

11

No optimices prematuramente. Mantenlo simple. Usar TCP en este caso está bien, y no veo ningún problema con su esquema actual.

UDP generalmente se usa para escenarios críticos de rendimiento, como en un juego de acción en línea, porque permite un control explícito sobre los paquetes individuales en lugar de trabajar sobre la abstracción de una capa de flujos como TCP. Sin embargo, aunque tiene cierta ganancia de velocidad al controlar exactamente cómo desea que se envíen los datos, UDP no maneja la pérdida de paquetes o el pedido de paquetes como TCP, en cuyo caso debe codificarlos usted mismo. Entonces, dado que este es un juego de cartas por turnos, dudo que quieras sacrificar la confiabilidad por la velocidad, así que usa TCP.

XiaoChuan Yu
fuente
Gracias por su respuesta, fue claro y parece responder a todo lo que pregunté.
LDM91
3

Incluso muchos MMO grandes y populares utilizan TCP exclusivamente. Hará todo lo que necesite con todas las características de eficiencia que necesita.

UDP requiere mucha complejidad adicional, la multidifusión requiere aún más complejidad, y no obtendrá nada de ellos. Si solo está interesado en aprender, haga una demostración técnica para usted, pero no piense que el proyecto en sí mismo estará mejor de alguna manera.

Si está interesado en usar UDP, su primera tarea básicamente será volver a implementar TCP sobre UDP, solo para asegurarse de que realmente comprende cómo lidiar con todos los problemas que TCP resuelve para usted: congestión control, retransmisión de paquetes perdidos, manejo duplicado retrasado, pedido de paquetes, protocolo de enlace de conexión confiable, secuencia de desconexión confiable, etc.

No es necesariamente difícil resolver todo eso, pero requiere una comprensión profunda de las redes, el protocolo IP y cómo se resuelven esos problemas.

A partir de ahí, la creación de la biblioteca para ofrecer características que TCP carece es donde realmente comienza la diversión. Usar un flujo de mensajes multiplexado sobre un flujo de paquetes, un control de congestión más eficiente, manejo de límite de velocidad, canales múltiples, configuración del canal (si el canal requiere mensajes en orden o no, si se permiten paquetes descartados, etc.), etc.

Te sugiero que leas la siguiente serie de artículos. No es perfecto y hace algunas afirmaciones muy cuestionables (comenzando con su sinsentido "nunca use TCP en juegos"), pero sus detalles técnicos son útiles para los nuevos programadores de red: http://gafferongames.com/networking-for-game- programadores / udp-vs-tcp /

Sean Middleditch
fuente
1
En la introducción a ese artículo, el autor declaró: "La elección que hagas depende completamente de qué tipo de juego quieres conectar en red. Entonces, a partir de este momento, y para el resto de esta serie de artículos, voy a asumir que quieres para conectar en red un juego de acción. Conoces juegos como Halo, Battlefield 1942, Quake, Unreal, CounterStrke, Team Fortress, etc. "
XiaoChuan Yu
Ah, me perdí eso cuando lo hojeé para asegurarme de que fuera tan bueno como lo recuerdo. Mi mal, lo siento.
Sean Middleditch
-1 para "Si está interesado en usar UDP, su primera tarea será básicamente volver a implementar TCP sobre UDP" , es una IMO muy incorrecta. Mucho más útil para aprender UDP en realidad haciendo cosas para las que se elige UDP.
o0 '.
@Lohoris: Eso no ayuda y ni siquiera es correcto. DEBE tener la capacidad de enviar mensajes garantizados en orden incluso con UDP. Debe poder enviar mensajes no garantizados en orden. Debe poder enviar mensajes fuera de servicio garantizados. Es más sencillo comenzar con el comportamiento similar a TCP porque requiere la implementación de todas las funciones requeridas y es más fácil de probar, e incluso por sí solo brinda funciones útiles como un control más directo del uso del ancho de banda y la latencia.
Sean Middleditch
@seanmiddleditch mal. No hay nada de malo en usar UDP y TCP en el mismo juego, por lo que no es necesario implementar una entrega garantizada a través de UDP.
o0 '.