Comment écrire un jeu en réseau? [fermé]

73

Basé sur Pourquoi est-il si difficile de développer un MMO? :

Le développement de jeux en réseau n'est pas anodin; il faut surmonter d’importants obstacles non seulement en termes de latence, mais aussi de prévention de la triche, de gestion de l’état et d’équilibrage de charge. Si vous n'avez pas l'habitude d'écrire un jeu en réseau, cet exercice d'apprentissage sera difficile.

Je connais la théorie sur les sockets, les serveurs, les clients, les protocoles, les connexions, etc.

Maintenant, je me demande comment on peut apprendre à écrire un jeu en réseau:

  • Comment équilibrer les problèmes de charge?
  • Comment gérer l'état du jeu?
  • Comment garder les choses synchronisées?
  • Comment protéger la communication et le client du reverse engineering?
  • Comment résoudre les problèmes de latence?
  • Quels éléments doivent être calculés en local et lesquels sur le serveur?
  • ...

Existe-t-il de bons livres, tutoriels, sites, articles intéressants ou autres questions à ce sujet?

Je cherche des réponses générales, mais des réponses spécifiques conviennent également pour apprendre la différence.

Tamara Wijsman
la source
4
Oui, il y a des livres, des tutoriels, des sites, des articles intéressants et d'autres questions à ce sujet.
Ricket
2
J'ai ajouté bounty pour pousser la question sans la modifier et donner aux utilisateurs une raison de répondre car cette question mérite des réponses. Ainsi, le meilleur répondant reçoit la réputation de son travail, mais il n'y a pas une seule réponse qui réponde à la question.
Tamara Wijsman le

Réponses:

61

En plus de l'article lié dans d'autres réponses, je peux parler un peu de l'expérience du projet Arianne .

Comment garder les choses synchronisées?

Nous avons construit le cadre « Marauroa » autour du concept d’actions et de perceptions: les actions sont envoyées du client au serveur portant les entrées de l’utilisateur, comme (marche à gauche, monstres d’attaque n ° 47, dites «bonjour»). Et les perceptions sont envoyées du serveur aux clients pour les informer de l’état du monde les concernant. Ces perceptions sont envoyées à chaque tour. En fonction du jeu, nous utilisons des temps de rotation de 30 ms à 300 ms.

Nous avons deux types de perceptions : une perception complète est envoyée lors de la connexion et lorsque le joueur entre dans une nouvelle zone (zone). Après cela, des perceptions différentielles sont envoyées, y compris uniquement les attributs modifiés (par exemple, la position) des objets modifiés, et bien sûr des objets nouveaux et supprimés.

Comment résoudre les problèmes de latence?

Nous croyons fermement que «le serveur a toujours raison». Le client fait certaines prédictions comme la marche en douceur, la vérification des collisions, etc. Mais si un client et le serveur ne sont pas d'accord sur quelque chose, le serveur gagne. Le sous-projet Stendhal (un RPG 2D) utilise un temps de rotation de 300 ms par défaut (avec beaucoup de lissage effectué côté client). Cela rend Stendhal très résistant au retard.

Remarque: Certains autres jeux font davantage confiance au client pour minimiser l'impact du décalage réseau. Dans WoW, il était souvent exploité dans l'un des champs de bataille appelé "Warsong Gulch". Un joueur avec le drapeau peut choisir entre deux options: au centre par un tunnel et une à droite pour monter la colline. Ainsi, un joueur tricheur court vers le tunnel, puis se retarde. Le serveur et les autres clients continueront à le voir courir vers lui. Mais après un peu de temps, ce client peut dire au serveur qu’il s’est dirigé vers la colline. WoW vérifiera que la distance entre les dernières coordonnées transmises et les coordonnées actuelles s’inscrit dans le segment temporel et l’acceptera.

Utilisation de UDP contre TCP

Dans les premières versions, nous utilisions UDP pour réduire la surcharge de TCP. Nous avons traité les paquets perdus nous-mêmes. Cela a parfaitement fonctionné aux débuts du projet. Mais lorsque le serveur a été déplacé d’une connexion DSL à la maison à un véritable centre de données, il ya plusieurs années, nous avons eu d’énormes problèmes. UDP est (ou du moins l'était il y a 5 ans) extrêmement gourmand en ressources processeur du pare-feu: le jeu de règles doit être appliqué à chaque paquet UDP. Pour TCP, toutefois, le jeu de règles ne s'applique qu'aux 3 premiers paquets. Après cela, la connexion est établie. Tous les paquets suivants contourneront le jeu de règles normal car ils sont dans la table de suivi des connexions ou parce qu’ils n’ont pas d’indicateur SYN.

Comment protéger la communication et le client du reverse engineering?

Arianne est complètement open source, cela inclut le client, le serveur, les graphiques, la musique. Et bien sûr, cela inclut notre documentation de protocole et même un analyseur utilisé pour le débogage.

Il est facile de protéger la communication contre le sniffing non autorisé par des tiers utilisant SSL.

Il est toutefois impossible de le protéger contre la rétro-ingénierie. Bien sûr, vous pouvez le masquer et utiliser des techniques anti-débogage. Mais en fin de compte, vous ne pouvez pas empêcher le reverse engineering des logiciels que vous cédez aux utilisateurs. Il y a une présentation très intéressante sur la façon dont Skype a été inversé malgré les développeurs qui ont mis beaucoup d'efforts dans les techniques anti-débogage: http://recon.cx/en/f/vskype-part1.pdf

Remarque: Il existe des pays dans lesquels l'ingénierie inverse est illégale ou qui permettent de placer un paragraphe dans la licence ou de ne pas autoriser l'ingénierie inverse. Mais il y a d'autres pays (comme celui dans lequel je vis) qui autorisent explicitement la rétro-ingénierie dans le cadre de l'élaboration de formats de stockage de données compatibles ou de protocoles de transmission, des paragraphes de la licence ou du ToS essayant de les rejeter qui sont nuls. (Tout dans cette section est à ma connaissance, je ne suis pas avocat)

Quels éléments doivent être calculés en local et lesquels sur le serveur?

Nous calculons tout ce qui concerne la logique du jeu sur le serveur. Le client prédit certains événements afin que le jeu se déroule sans heurts. Mais au final, le serveur a toujours raison.

Les événements prédits sont par exemple l’arrêt du mouvement lorsqu’une collision est touchée. Stendhal utilise une grille pour positionner les éléments. Et du point de vue du serveur, le coin supérieur gauche de chaque entité se trouve exactement sur une case. Mais le client les déplacera sans problème entre les tuiles. Il va aussi dessiner le pseudo effet 3d. Donc, une entité qui a une base de 1x1 peut être plus élevée dans le client.

Comment équilibrer les problèmes de charge?

Essayez de garder cela aussi simple que possible pour faciliter la maintenance.

L'équilibrage de la charge du contenu statique est bien connu dans le domaine des clusters de serveurs http et des réseaux de distribution de contenu.

Un concept plutôt simple d'équilibrage de la charge des services de jeu consiste à fractionner les serveurs entre régions / zones. Les zones AC sont donc sur un serveur et les zones DF sur un autre. Cela est particulièrement facile si vous ne pouvez pas regarder à partir de zones d’un jeu donné vers des zones d’un autre jeu. Vous devez y mettre quelques vérifications pour qu'un client ne puisse se connecter qu’à un serveur de zone responsable de la zone dans laquelle se trouve le lecteur.

Le moyen le plus simple de transférer des lecteurs d’un serveur à l’autre est de les écrire dans la base de données, d’indiquer au client de se connecter à l’autre serveur de zone et de les déconnecter du serveur actuel. Le client se connectera ensuite au nouveau serveur de zone qui le chargera à partir de la base de données. (Étant donné que vous avez de toute façon besoin du code de charge depuis / store vers la base de données, la communication directe entre les serveurs pour le transfert peut être mise en œuvre ultérieurement).

Certains services globaux supplémentaires sont nécessaires via: Au moment de la connexion, il est demandé aux clients de se connecter au serveur de zone approprié. Et vous voudrez peut-être un système de discussion mondial.

Je suis allé plus en détail sur ce sujet dans Comment l'équilibre des charges est-il atteint dans les MMO?

Hendrik Brummermann
la source
1
Vous avez mentionné que le protocole UDP nécessite un peu plus de processeur, mais vous avez omis de mentionner que TCP nécessite au moins trois allers-retours entre le client et le serveur avant que le paquet ne soit traité, ET les paquets sont mis en mémoire tampon jusqu'à ce que tous les paquets précédents aient été reçus, ce qui risque de vous ridiculiser. temps d'attente pour les paquets qui ne sont même plus pertinents. Cela semble être une chose importante à mentionner.
BlueRaja - Danny Pflughoeft le
2
@Danny, Trois paquets sont nécessaires pour établir une nouvelle connexion TCP: client à serveur: SYN, serveur à client: SYN ACK, client à serveur: ACK + données. C'est un aller-retour de plus qu'UDP, mais cela ne se produit qu'au tout début lorsque le client contacte le serveur pour la première fois. Dans une connexion établie, chaque paquet est traité immédiatement sans aucun aller-retour supplémentaire. Il y aura une réponse ACK mais les données reçues sont déjà traitées alors que les paquets ACK sont renvoyés.
Hendrik Brummermann le
1
@Danny, TCP gère les pertes de paquets automatiquement et de manière très efficace. Il est difficile de réimplémenter cela en utilisant UDP; à moins que votre protocole ne fonctionne correctement avec des paquets aléatoires non livrés. Le problème suivant est que TCP s'assure que l'ordre des paquets, tandis que les paquets UDP peuvent être reçus dans le mauvais ordre. Là encore, il est difficile de réimplémenter cela vous-même, à moins que vous ne puissiez simplement ignorer des paquets plus anciens, basés par exemple sur un compteur de paquets. Si un temps de réponse très court est requis pour TCP, l'algorithme de Nagle doit être désactivé.
Hendrik Brummermann le
Il semble que vous ayez défendu votre position avec véhémence sans vous attaquer au très réel problème du décalage TCP. Le vrai problème, c'est peut-être le choix d'un pare-feu matériel au lieu d'un protocole résistant aux attaques DDoS
MickLH
27

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

Est un excellent ensemble d’articles sur divers problèmes et solutions concernant la mise en réseau de jeux.

jsimmons
la source
1
+1, mais s'il vous plaît ne leur faites pas confiance aveuglément. D'après mon expérience, par exemple, utiliser UDP pour réinventer la fonctionnalité TCP n'est pas une bonne idée. UPD n'est utile que si les paquets perdus n'ont aucun impact, c'est-à-dire que chaque paquet UDP contient l'état complet du monde. WoW utilise TCP, SL est en train de passer d'UDP à TCP (même HTTP pour le contenu statique) et a considérablement amélioré les performances avec ces changements.
Hendrik Brummermann
7
Cependant, vous ne réinventez pas les fonctionnalités TCP, pas toutes. La sémantique du contrôle de flux TCP et de la perte de paquets est terrible pour un jeu nécessitant une connexion à faible latence. TCP n'est utile que si vous ne vous souciez pas de la latence ou de la réduction de la bande passante requise.
Jsimmons
2
Second Life a massivement amélioré les performances en passant d'UDP à HTTP via TCP: blogs.secondlife.com/community/technology/blog/2010/08/13/…
Hendrik Brummermann
5
Euh pas vraiment, ils ont amélioré les performances de leurs flux d'actifs en modifiant son fonctionnement. L'utilisation de HTTP / TCP dans cette instance leur a facilité la mise en œuvre, pas plus rapide. Je pourrais également noter que zeromq est un projet intéressant qui peut très bien s’adapter au jeu en réseau. zeromq.org
jsimmons
8

Selon le type de jeu que vous écrivez, vous pourrez peut-être éviter une partie de la programmation réseau de bas niveau. Certains types de jeux ne nécessitent pas beaucoup de communication entre les clients et le serveur. Dans de tels cas, on pourrait choisir d'utiliser un cadre de niveau supérieur. Par exemple, je développe un jeu de stratégie tour par tour en C # / .NET. Les jeux de stratégie tour par tour sont quelque peu uniques en ce sens que la grande majorité des communications client / serveur se font au début et à la fin d'un tour, avec relativement peu d'intervalle entre les deux. Ainsi, j'ai choisi d'utiliser Windows Communication Foundation (WCF), une infrastructure de communication de haut niveau conçue principalement pour les services Web. Au lieu de travailler directement avec les sockets et tous ces gunk de réseau de bas niveau, je peux faire ce qui semble être des appels de méthode standard, et laissez WCF s'occuper du protocole et des couches de transport pour moi. La seule fois où j'ai eu à traiter avec des problèmes de réseau de bas niveau a été la configuration de mes points de terminaison, ce qui est plutôt une transaction ponctuelle dans un fichier de configuration. Il peut encore être nécessaire d'implémenter une logique de sérialisation personnalisée, mais vous devrez le faire de la même manière.

Mike Strobel
la source
8

La question est beaucoup trop large. Les réponses pourraient remplir un site Web à eux seuls. Mais, il y a des livres qui abordent ce sujet, principalement ces deux:

Notez que même ces livres ne sont pas un guide complet, mais plutôt un ensemble d’idées et d’approches que vous pouvez utiliser, dont certaines ne fonctionneront pas ensemble, voire sont contradictoires. Généralement, cela suppose une certaine expérience dans le développement de jeux, d'applications réseau ou, idéalement, des deux.

(Notez que je parle davantage des MMO dans la question initiale - un "jeu en réseau" pourrait signifier toutes sortes de choses, d'un jeu texte basé sur PHP à un MMO, et les sous-questions ci-dessus ne font pas toutes appliquer à chaque type.)

Kylotan
la source
7

Comment équilibrer les problèmes de charge?

taille géographique fixe + plusieurs instances est la solution la plus simple. Les gars travaillant sur SWG ont essayé la taille dynamique et l'ont regretté.

Comment gérer l'état du jeu?

Le serveur fait autorité.

Comment garder les choses synchronisées?

Mises à jour périodiques de synchronisation à partir du serveur. (je ne sais pas trop quelle est la préoccupation ici)

Comment protéger la communication et le client du reverse engineering?

Impossible. Assurez-vous simplement de ne faire confiance à rien de ce que vous recevez du client et que le serveur fait autorité.

Comment résoudre les problèmes de latence?

Cela va loin, mais superficiellement, vous exécutez la même simulation sur le client que le serveur et lorsque la synchronisation se produit, corrigez les choses. Toutes les décisions prises sur le client sont également simulées sur le serveur. Il peut donc y avoir de mauvaises décisions, mais les choses se passent généralement bien.

Quels éléments doivent être calculés en local et lesquels sur le serveur?

Pensez au client comme exécutant une simulation ne faisant pas autorité de ce qui se passe sur le serveur. La réactivité est la clé de l'expérience du joueur. Vous devez donc faire quelque chose à chaque fois qu'un joueur prend une décision, même s'il ne fait que commencer une mesure.

À vrai dire, bon nombre de ces problèmes sont orthogonaux et peuvent faire l’objet de solutions plus tard. Commencez simplement à jouer et ne vous inquiétez pas trop de ces choses.

Aaron Brady
la source
4

Cette question est très large. C'est également un domaine très difficile à maîtriser. Les programmeurs de réseau sont très recherchés dans l'industrie avec un salaire correspondant, ce qui indique un peu qu'il s'agit d'un domaine «non résolu». Y at-il des livres là-bas, oui, beaucoup. Y at-il de bons livres là-bas, sans aucun doute. Y a-t-il des livres qui répondront à vos questions? ... Je ne le pense pas. Ils ont peut-être des solutions qui fonctionnent dans certaines situations ou des indications sur ce qu’il faut rechercher, mais presque toutes vos questions dépendent du jeu ... c’est un domaine dans lequel vous devrez vraiment travailler beaucoup vous-même, c’est tellement apparemment trivial et cela peut mal tourner de nombreuses façons (incontrôlées).

Kaj
la source