2010-11-23 6 views
10

Je crée un jeu multijoueur basé sur un navigateur Web. J'ai déterminé que les websockets sont la meilleure façon de gérer les communications étant donné sa nature en temps réel. Le client utilise un canevas HTML5 pour rendre le jeu et les websockets pour communiquer avec l'hôte.Serveur de jeu PHP, plusieurs clients TCP?

J'ai choisi d'utiliser PHP pour héberger le jeu car il semble être préféré par les hébergeurs. Je n'ai pas utilisé PHP auparavant mais j'ai fait des choses similaires avec des websockets en Java, mais en me basant fortement sur le multithreading.

J'ai regardé quelques tutoriels sur les sockets php avec plusieurs clients; mais la plupart d'entre eux font des choses comme bifurquer de nouveaux processus pour chaque client. Puisque je vais avoir une boucle de jeu en cours d'exécution, je ne pense pas que ce soit approprié. Ce que j'essaye de réaliser est un moyen d'assigner des ports à chaque client pendant qu'ils se relient, en écoutant de nouveaux clients, en échangeant des données avec la liste courante de clients et en exécutant la boucle de jeu tous ensemble.

Les endroits où je besoin d'aide sont:

  • Comment trouver et affecter des ports à de nouveaux clients, informer le client de ce port, et le nettoyer quand ils se déconnectent.
  • Comment faire ci-dessus, et toutes les autres transactions de socket, sans bloquer la boucle de jeu. Il serait acceptable d'accepter des messages de clients en morceaux partiels et d'agir uniquement sur un message complet. Quelqu'un peut-il me donner des conseils techniques sur la façon d'atteindre ces objectifs?

Je ne pense pas que tout cela ressemble trop à demander à PHP mais corrigez-moi si je me trompe!

Un pseudo-code de ce que j'aimerais idéalement réaliser côté serveur. Aucune des fonctions ne doit bloquer: Clients de tableau;

while(gamerunning) 
{ 
    CheckForNewClients(); 
    GetStatusFromClients(); 
    DoGameUpdate(); 
    SendGameStateToClients(); 
} 

[Mise à jour] Pour toute personne intéressée, je créé une application dédiée supportant les sockets Web (en particulier en utilisant Java et la bibliothèque socket web « TooTallNates ») plutôt que d'un service Web réel car il semblait plus logique, Bien que, incidemment, il semble que la plupart des navigateurs Web ont jeté des sockets Web à la poubelle en raison de problèmes de sécurité.

+1

Dans le cas où vous pouvez obtenir un VPS ou quelque chose qui vous permet d'exécuter Node.js dessus, je suggère fortement de prendre le chemin du nœud. Les serveurs multijoueurs dans Node.js sont un jeu d'enfant. –

+0

node.js n'est-il pas une solution côté client pour les websockets? –

+0

non, nodejs en bref est flamboyant rapide, eventdriven, serveur javascript pour les serveurs d'écriture. –

Répondre

5

Je ne suggère pas d'utiliser PHP pour ce type d'application. PHP ne supporte pas officiellement le multithreading et l'exécution d'un script PHP pendant une période indéfinie (comme un serveur) n'est pas vraiment une fonctionnalité annoncée.

Bien sûr, vous pouvez essayer de faire de l'histoire :)

(s'il vous plaît me corriger si je me trompe)

+2

Peut-être que j'ai fait l'histoire ... J'ai déjà fait des démons de socket server avec PHP (parce que mon employeur a appliqué cette technologie) et je ne vois pas quel est le problème. Cela fonctionne très bien, avec un seul processus ou plusieurs. – netcoder

+1

Même ici, j'ai actuellement écrit un backend de jeu en PHP (en tant que démon). Il écoute/écrit des messages via une passerelle XMPP. Jusqu'à présent, cela fonctionne très bien (pas super rapide, mais ne peut pas battre PHP utilisabilité). –

+1

@Kendall: Je ne pense pas que la vitesse est vraiment un problème. J'ai aussi écrit des démons socket en Java, et PHP bat la plupart d'entre eux en vitesse. Premièrement, il n'y a pas de JVM pour commencer. Deuxièmement, PHP est très proche des sockets raw C, contrairement à la couche socket abstraite de Java. – netcoder

7

Vous avez vraiment besoin d'utiliser un démon PHP afin de le faire efficacement (et il doit être PHP 5.3). J'ai écrit un aperçu assez complet de l'utilisation PHP for daemon processes. Quoi que vous choisissiez, je vous suggère d'utiliser un système de boucle d'exécution basé sur les événements.

J'ai conçu une bibliothèque de base RunLoop appelée LooPHP qui pourrait probablement être utile, surtout si vous allez traiter avec *_select. Je serais ravi de répondre à vos questions à ce sujet.

EDIT:

Dans un événement système basé vous n'avez pas simplement while une liste de commandes, vous réagissez à un auditeur. Par exemple ...

Au lieu de faire:

while(1) { 
    ... /* listen, react */ 
} /* repeat */ 

Exécuter boucles travail en enregistrant écoute (prises, et d'autres générateurs d'événement async)

class ReactClass { ... } 

$loop = new LooPHP_EventLoop(new ReactClass); 

//add one time event 
$loop->addEvent(function() { 
    print "This event was called 0.5 second after being added\n"; 
}, 0.5 /* in seconds */); 

//this creates a repeating event, this is called right away and repeats 
$add_event = function() use ($loop, &$add_event) { 
    print "This event is REPEATEDLY called 0.1 every second\n"; 
    $loop->addEvent($add_event, 0.1); 
}; 
$add_event(); 

//start the loop processing, no events are processed until this is done 
$loop->run(); //php doesn't leave this call until the daemon is done 
exit(0); //cleanly exit 

Le cas ci-dessus est très simple 1 source EventLoop et des fonctions temporisées ajoutées manuellement (elles peuvent être ajoutées même à partir d'un appel à ReactClass). Dans l'application que je suis en train de travailler, j'avais besoin d'avoir un flux d'événements asynchrone dans le backend (via une socket), puis d'avoir la possibilité d'appeler des fonctions arbitrairement décalées par rapport à l'événement d'origine (pour les clients expirés, etc).

Si vous souhaitez d'autres exemples, vous pouvez les trouver à github.

J'espère que vous trouverez cela utile.

+0

any1 savoir ici sur le fonctionnement de Garena? J'ai besoin d'aide pour ça aussi ... – booota

+0

J'aime le look de ça. Pourriez-vous me montrer comment configurer ceci pour que les fonctions de l'événement aient accès à un tableau d'objets constamment mis à jour dans une boucle de jeu séparée? –

+0

@Toby Wilson J'ai mis à jour mon message. Faites-moi savoir si cela vous a été utile. –

Questions connexes