¿Cómo escribir un juego en red? [cerrado]

73

Basado en ¿Por qué es tan difícil desarrollar un MMO? :

El desarrollo de juegos en red no es trivial; Hay grandes obstáculos que superar no solo en la latencia, sino también en la prevención de trampas, la gestión del estado y el equilibrio de carga. Si no tienes experiencia en escribir un juego en red, este será un ejercicio de aprendizaje difícil.

Conozco la teoría sobre sockets, servidores, clientes, protocolos, conexiones y esas cosas.

Ahora me pregunto cómo se puede aprender a escribir un juego en red:

  • ¿Cómo equilibrar los problemas de carga?
  • ¿Cómo gestionar el estado del juego?
  • ¿Cómo mantener las cosas sincronizadas?
  • ¿Cómo proteger la comunicación y el cliente de la ingeniería inversa?
  • ¿Cómo solucionar problemas de latencia?
  • ¿Qué cosas deben calcularse localmente y qué cosas en el servidor?
  • ...

¿Hay buenos libros, tutoriales, sitios, artículos interesantes u otras preguntas al respecto?

Estoy buscando respuestas amplias, pero las específicas también están bien para aprender la diferencia.

Tamara Wijsman
fuente
44
Sí, hay libros, tutoriales, sitios, artículos interesantes y otras preguntas al respecto.
Ricket
2
Agregué recompensas para impulsar la pregunta sin modificarla y dar a los usuarios una razón para responder, ya que esta pregunta merece respuestas, por lo tanto, el mejor respondedor obtiene reputación por su trabajo, pero no hay una sola respuesta que responda a la pregunta.
Tamara Wijsman

Respuestas:

61

Además del artículo vinculado en otras respuestas, puedo contar un poco sobre la experiencia del Proyecto Arianne .

¿Cómo mantener las cosas sincronizadas?

Tenemos el marco de trabajo " Marauroa " en torno al concepto de acciones y percepciones: las acciones se envían desde el cliente al servidor llevando la entrada del usuario como (caminar a la izquierda, atacar a los monstruos # 47, decir 'hola'). Y las percepciones se envían desde el servidor a los clientes informándoles sobre el estado del mundo que los rodea. Esas percepciones se envían cada turno. Dependiendo del juego, usamos tiempos de giro de 30ms a 300ms.

Tenemos dos tipos de percepciones : se envía una percepción completa al iniciar sesión y cuando el jugador ingresa a una nueva área (zona). Después de eso, se envían percepciones diferenciales que incluyen solo los atributos modificados (por ejemplo, la posición) de los objetos modificados y, por supuesto, los objetos nuevos y eliminados.

¿Cómo solucionar problemas de latencia?

Creemos firmemente en "el servidor siempre tiene la razón". El cliente hace algunas predicciones como caminar sin problemas, verificaciones de colisiones, etc. Pero si un cliente y el servidor no están de acuerdo con algo, el servidor gana. El subproyecto Stendhal (un RPG 2D) utiliza un tiempo de giro de 300 ms de forma predeterminada (con mucho suavizado hecho del lado del cliente). Esto hace que Stendhal sea muy resistente al retraso.

Nota: Algunos otros juegos confían en el cliente hasta cierto punto para minimizar el impacto del retraso de la red. En WoW a menudo se explotaba en uno de los campos de batalla llamado "Warsong Gulch". Hay dos formas en que un jugador con la bandera puede elegir: Encendido en el medio a través de un túnel y uno en la mira derecha que sube la colina. Entonces, un jugador infiel corre hacia el túnel y luego se atrasa. El servidor y los otros clientes continuarán viéndolo correr hacia él. Pero después de un tiempo, este cliente puede decirle al servidor que se dirigió hacia la colina. WoW verificará que la distancia entre las últimas coordenadas transmitidas y las actuales se ajuste al segmento de tiempo y lo aceptará.

Uso de UDP vs. TCP

En versiones anteriores, usábamos UDP para reducir la sobrecarga de TCP. Manejamos paquetes perdidos por nuestra cuenta. Esto funcionó perfectamente en los primeros días del proyecto. Pero cuando el servidor se trasladó de una conexión DSL doméstica a un centro de datos real hace varios años, tuvimos grandes problemas. UDP es (o al menos hace 5 años) extremadamente exigente con la potencia de CPU del hardware del firewall: el conjunto de reglas debe aplicarse a cada paquete UDP. Sin embargo, para TCP, el conjunto de reglas solo se aplica a los primeros 3 paquetes. Después de eso se establece la conexión. Todos los siguientes paquetes omitirán el conjunto de reglas normal porque están en la tabla de seguimiento de conexión o porque no tienen un indicador SYN.

¿Cómo proteger la comunicación y el cliente de la ingeniería inversa?

Arianne es completamente de código abierto, esto incluye el cliente, el servidor, los gráficos, la música. Y, por supuesto, eso incluye nuestra documentación de protocolo e incluso un analizador utilizado para la depuración.

Es fácil proteger la comunicación contra el rastreo no autorizado por parte de terceros que utilizan SSL.

Sin embargo, es imposible protegerlo contra la ingeniería inversa. Claro que puedes ofuscarlo y usar técnicas anti depuración. Pero al final no puede evitar la ingeniería inversa del software que regala a los usuarios. Hay una presentación muy interesante sobre cómo se invirtió Skype a pesar de que los desarrolladores pusieron mucho esfuerzo en las técnicas contra la depuración: http://recon.cx/en/f/vskype-part1.pdf

Nota: Hay algunos países en los que la ingeniería inversa es ilegal o que permiten incluir un párrafo en la licencia o ToS que no permiten la ingeniería inversa. Pero hay otros países (como el que estoy viviendo) que permiten explícitamente la ingeniería inversa en el contexto del desarrollo de formatos de almacenamiento de datos compatibles o protocolos de transmisión, párrafos en la licencia o ToS que intentan rechazar que son nulos. (Todo lo que se incluye en esta sección es, por lo que sé, no soy abogado)

¿Qué cosas deben calcularse localmente y qué cosas en el servidor?

Calculamos todo lo relacionado con la lógica del juego en el servidor. El cliente predecirá ciertos eventos para que el juego funcione sin problemas. Pero al final el servidor siempre tiene la razón.

Los eventos predichos son, por ejemplo, la detención del movimiento cuando se golpea una colisión. Stendhal usa una cuadrícula para posicionar elementos. Y desde el punto de vista del servidor, la esquina superior izquierda de cada entidad está exactamente en un cuadrado. Pero el cliente los moverá suavemente entre los mosaicos. También dibujará el pseudo efecto 3d. Entonces, una entidad que tiene una base de 1x1 puede ser más alta en el cliente.

¿Cómo equilibrar los problemas de carga?

Trate de mantener esto lo más simple posible, para facilitar el mantenimiento.

El equilibrio de carga de contenido estático es bien conocido en el área de clústeres de servidores http y redes de distribución de contenido.

Un concepto bastante simple para el equilibrio de carga de los servicios de juegos es dividir servidores en regiones / zonas. Entonces las zonas AC están en un servidor y las zonas DF están en otro. Esto es especialmente fácil si no puede mirar desde zonas en un conjunto a zonas en otro conjunto. Debe poner algunas comprobaciones allí para que un cliente solo pueda conectarse a un servidor de zona responsable de la zona en la que se encuentra el jugador.

La forma más fácil de transferir jugadores de un servidor a otro es escribirlos en la base de datos, decirle al cliente que se conecte al otro servidor de zona y desconectarlos del actual. El cliente se conectará al nuevo servidor de zona que lo cargará desde la base de datos. (Como necesita la carga desde / almacenar al código de la base de datos de todos modos, la comunicación directa entre los servidores para la transferencia puede implementarse más adelante).

Se necesitan algunos servicios globales adicionales a través de: Al iniciar sesión, se debe indicar a los clientes que se conecten al servidor de zona correcto. Y es posible que desee un sistema de chat mundial.

Entré en detalles sobre este tema en ¿Cómo se logra el equilibrio de carga en los MMO?

rev. Hendrik Brummermann
fuente
1
Usted mencionó que UDP requiere un poco más de CPU, pero no mencionó que TCP requiere al menos tres viajes entre el cliente y el servidor antes de que se procese el paquete, Y los paquetes se almacenan en el búfer hasta que se hayan recibido todos los paquetes anteriores, lo que significa que puede experimentar ridículas cantidades de retraso esperando paquetes que ya ni siquiera son relevantes. Parece una cosa importante para mencionar.
BlueRaja - Danny Pflughoeft
2
@Danny, se requieren tres paquetes para iniciar una nueva conexión TCP: cliente a servidor: SYN, servidor a cliente: SYN ACK, cliente a servidor: ACK + datos. Es un viaje de ida y vuelta más que UDP, pero solo ocurre al principio cuando el cliente contacta al servidor por primera vez. En una conexión establecida, cada paquete se procesa inmediatamente sin ningún viaje de ida y vuelta adicional. Habrá una respuesta ACK pero que los datos recibidos ya se procesan mientras los paquetes ACK viajan de regreso.
Hendrik Brummermann
1
@Danny, TCP maneja la pérdida de paquetes automáticamente y de una manera bastante eficiente. Es difícil reimplementar que usted mismo use UDP; a menos que su protocolo esté bien con paquetes aleatorios no entregados. El siguiente problema es que TCP garantiza el orden de los paquetes, mientras que los paquetes UDP pueden recibirse en el orden incorrecto. Nuevamente, es difícil volver a implementarlo usted mismo, a menos que pueda ignorar los paquetes más antiguos, por ejemplo, basados ​​en un contador de paquetes. Si se requiere un tiempo de respuesta muy corto para TCP, el algoritmo de Nagle debe deshabilitarse.
Hendrik Brummermann
Parece que has defendido con vehemencia tu posición sin abordar el verdadero problema del retraso de TCP. Quizás el verdadero problema sea su elección de un firewall de hardware en lugar de un protocolo resistente a DDoS
MickLH
27

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

Es un gran conjunto de artículos sobre diversos problemas y soluciones relacionados con las redes de juegos.

jsimmons
fuente
1
+1, pero no confíes en ellos a ciegas. Según mi experiencia, por ejemplo, no es una buena idea usar UDP y reinventar la función de TCP. UPD es útil solo si los paquetes perdidos no tienen ningún impacto, es decir, cada paquete UDP contiene el estado relevante completo del mundo. WoW usa TCP, SL está en proceso de pasar de UDP a TCP (incluso HTTP para contenido estático) y ha mejorado significativamente el rendimiento con estos cambios.
Hendrik Brummermann
77
Sin embargo, no está reinventando las características de TCP, no todas al menos. El control de flujo TCP y la semántica de pérdida de paquetes son terribles para un juego que requiere una conexión de baja latencia. TCP solo es útil si no le importa la latencia o minimizar el ancho de banda requerido.
jsimmons
2
Second Life mejoró enormemente el rendimiento al pasar de UDP a HTTP a través de TCP: blogs.secondlife.com/community/technology/blog/2010/08/13/…
Hendrik Brummermann
55
Uh, en realidad no, mejoraron el rendimiento de su transmisión de activos al cambiar su funcionamiento. El uso de HTTP / TCP en esa instancia les facilitó la implementación, no más rápido. También podría señalar que zeromq es un proyecto interesante, y puede escalar muy bien para la red de juegos. zeromq.org
jsimmons
8

Dependiendo del tipo de juego que estés escribiendo, es posible que puedas evitar parte de la programación de red de bajo nivel. Algunos tipos de juegos no requieren mucha comunicación de ida y vuelta entre los clientes y el servidor. En tales casos, uno podría optar por utilizar un marco de nivel superior. Por ejemplo, estoy desarrollando un juego de estrategia por turnos en C # /. NET. Los juegos de estrategia por turnos son algo únicos, ya que la gran mayoría de la comunicación cliente / servidor se produce al principio y al final de un turno, con relativamente poco en el medio. Por lo tanto, opté por utilizar Windows Communication Foundation (WCF), un marco de comunicaciones de alto nivel diseñado principalmente para servicios web. En lugar de trabajar directamente con sockets y toda esa basura de redes de bajo nivel, puedo hacer lo que parecen ser llamadas a métodos estándar, y dejar que WCF se encargue del protocolo y las capas de transporte por mí. La única vez que tuve que lidiar con las cosas de la red de bajo nivel fue cuando configuré mis puntos finales, que es más o menos una sola vez en un archivo de configuración. Puede que aún sea necesario implementar alguna lógica de serialización personalizada, pero debería hacer ese tipo de cosas independientemente.

Mike Strobel
fuente
8

La pregunta es demasiado amplia. Las respuestas podrían llenar un sitio web por su cuenta. Pero, hay libros que tocan esto, principalmente estos dos:

Tenga en cuenta que incluso estos libros no son una guía completa, sino que son una colección de ideas y enfoques que puede usar, algunos de los cuales no funcionarán juntos, o incluso son contradictorios. Por lo general, supone cierta experiencia desarrollando juegos, aplicaciones de red o, idealmente, ambos.

(Tenga en cuenta que estoy hablando más sobre los MMO en la pregunta original: un 'juego de red' podría significar todo tipo de cosas, desde un juego de texto basado en PHP hasta un MMO, y las subpreguntas anteriores no todas aplicar a cada tipo).

revs Kylotan
fuente
7

¿Cómo equilibrar los problemas de carga?

tamaño geográfico fijo + instancias múltiples es la solución más fácil. Los chicos que trabajan en SWG probaron el tamaño dinámico y lo lamentaron.

¿Cómo gestionar el estado del juego?

El servidor tiene autoridad.

¿Cómo mantener las cosas sincronizadas?

Actualizaciones periódicas de sincronización del servidor. (no estoy seguro de cuál es la preocupación aquí)

¿Cómo proteger la comunicación y el cliente de la ingeniería inversa?

Imposible. solo asegúrese de no confiar en nada de lo que reciba del cliente y de que el servidor tenga autoridad.

¿Cómo solucionar problemas de latencia?

Esto va muy lejos, pero superficialmente ejecutas la misma simulación en el cliente que en el servidor y cuando ocurre la sincronización, arregla las cosas. Todas las decisiones tomadas en el cliente también se simulan en el servidor, por lo que puede haber malas decisiones, pero las cosas generalmente funcionan.

¿Qué cosas deben calcularse localmente y qué cosas en el servidor?

Piense en el cliente como si ejecutara una simulación no autorizada de lo que está sucediendo en el servidor. La capacidad de respuesta es clave para la experiencia del jugador, por lo que debes hacer algo cada vez que un jugador toma una decisión, incluso si solo está comenzando un compás.

A decir verdad, muchos de estos problemas son ortogonales y pueden aplicarse soluciones más adelante. Simplemente comienza a hacer el juego y no te preocupes demasiado por estas cosas.

Aaron Brady
fuente
4

Esta pregunta es muy amplia. También es un área muy difícil de dominar, los programadores de red son muy buscados en la industria con un salario equivalente, lo que indica que es un área 'no resuelta'. ¿Hay libros por ahí? Sí, muchos. ¿Hay buenos libros por ahí, sin duda? ¿Hay libros por ahí que responderán a sus preguntas? ... No lo creo. Es posible que tengan soluciones que funcionen en algunas situaciones o indicadores sobre qué buscar, pero casi todas sus preguntas dependen del juego ... esta es un área en la que realmente tendrá que trabajar mucho solo, aparentemente trivial y puede salir mal de muchas maneras (no controladas).

Kaj
fuente