serveurs de sockets en java,perl,php,c++
Accueil L'offre Tarifs YSServer Tutoriaux Support Espace client Forum Legal
serveurs de sockets en java,perl,php,c++
Chat multi-room
your-socket
Bienvenue, Invité. Veuillez vous connecter ou vous enregistrer.
Avez-vous perdu votre courriel d'activation?Bienvenue.
Septembre 04, 2010, 10:55:08

Connexion avec identifiant, mot de passe et durée de la session
Recherche:     Recherche +
De nouveaux tutoriaux sont aujourd'hui disponibles.
1150 Messages dans 138 Sujets par 9690 Membres
Dernier membre: semiaddict
* Accueil Aide Recherche Identifiez-vous Enregistrez-vous
+  your-socket
|-+  Tutoriaux
| |-+  Niveau 2
| | |-+  Chat multi-room
« sujet précédent | | sujet suivant »
Pages: [1] Imprimer
Auteur Sujet: Chat multi-room  (Lu 5136 fois)
seal3
Administrator
Hero Member
*****
Messages: 504


Voir le profil
Chat multi-room
« le: Août 22, 2005, 04:56:06 »

Dans ce tutorial, nous allons créer chat dans lequel chaque client peut choisir son salon (room) et voir tous ceux qui s'y trouvent.

Vous pouvez directement observer le résultat de ce tutorial en ligne.

Dans un premier temps, nous allons nous occuper de la partie serveur toujours basée sur le serveur de ce tutorial. Nos explications seront en php puisque il s'agit du langage le plus rependu.

L'équivalent en perl est aussi disponible au bas de cette page. Globalement, le perl et le php sont assez proches pour pouvoir passer de l'un a l'autre facilement.

Voici donc la base de notre serveur :

Code:
<?php
$mainsock
= socket_create(AF_INET, SOCK_STREAM, 0);
socket_set_option($mainsock, SOL_SOCKET,SO_REUSEADDR, 1);
socket_bind($mainsock, "127.0.0.1", 22222) or die('Could not bind to address');
socket_listen($mainsock);
///////////////////

$clients=Array();
$compteur=0;
echo(
"En attente d'un client !\n");



while(
true){
$toread=Array();
array_push($toread,$mainsock);
for ($i=0;$i<count($clients);$i++){ // pour tous les clients
array_push($toread,$clients[$i]["SOCKET"]);
}

socket_select($toread,$a=null,$a=null,$a=null);

if(in_array($mainsock, $toread)){// le mainsock est dans le tableau $toread.
// c'est notre mainsock donc un nouveau client
$sock=socket_accept($mainsock);
echo("Arrivée d'un nouveau client !\n");
$compteur++;
$nb=count($clients);
$clients[$nb]["SOCKET"]=$sock;
$clients[$nb]["UID"]=$compteur;
}else{
// c'est un client qui dit quelque chose
for ($i=0;$i<count($clients);$i++){ // on cherche le client
if(in_array($clients[$i]["SOCKET"], $toread)) { // celui la est dans le tableau toread
$input = socket_read($clients[$i]["SOCKET"], 1024);
if($input==null){
/// deconnection du client !
for ($j=0;$j<count($clients);$j++){ // on le cherche dans le tableau
if($clients[$j]==$clients[$i]){ // trouvé
//////////////////////////////////////////////////Perte d'un client



//////////////////////////////////////////////////
echo("Deconnection du client ".$clients[$j]["UID"]."\n");
array_splice($clients,$j,1); // on le retire du tableau
$i--;
}
}
}else{
//////////////////////////////////////////////////Message d'un client



//////////////////////////////////////////////////
}
}
}
}
}


function
sendToAll($sauf,$msg){
global $clients;

for($i=0;$i<count($clients);$i++){ // pour tous les clients sauf celui qui envoie
if($sauf!=$clients[$i]["UID"]){
socket_write($clients[$i]["SOCKET"],$msg.chr(0));
}
}
}
php?>



Dans le code ci-dessus nous avons mis en évidence (séparés par des ////) les deux zones dans lesquelles nous allons travailler.

Ces deux zones représentent : la gestion de déconnection d'un client et de réception de messages.


Il nous faut d'abord décider du format des messages envoyés par un client. Voici un exemple des messages que le serveur peut recevoir. Chaque message commence par une action suivis de paramètres séparés par un caractère spécial (nous choisissons le signe "="). Nous n'utilisons pas d'XML qui est trop gourmant en CPU et bande passante :

INIT=1256=toto
Le client transmettra donc toutes ses informations quand il serra prêt à être affiché sur l'écran des autres. Ces informations seront enregistrées par le serveur sous forme de variables dans l'objet client afin que si un autre se connecte, on puisse lui transmettre toutes les informations des autres clients déjà en ligne. Le premier paramètre (1256) est donc la couleur de du client. Le second (toto) est son pseudo.

SETROOM=room
Le client change de room. Le paramètre est donc le nom de la room.

MSG=mon texte
Un client viens de chatter on récupère le texte. Le serveur connaissant la room du client s'occupe de transmettre les informations aux autres.

Ensuite les messages que le serveur peut envoyer aux clients :

NEWONE=12556=toto
On informe le client qu'un nouveau viens d'arriver. Le premier paramètre est sa couleur. Le second est son pseudo.

MSG=le message=couleur
Un client viens de chatter, le serveur en informe les autres de la même room.

USERLIST=pseudo1,couleur1=pseudo2,couleur2
On informe les clients de ceux qui se trouve dans cette room. Chaque paramètre est un couple pseudo/couleur séparé par une ",".

ROOMLIST=nom1,nombre1=nom2,nombre2
On informe les clients de la liste des room ouvertes avec le nombre de connectés.


A l'initialisation, le client se connecte, choisis (aléatoirement pour simplifier) la couleur de son texte, transmet au serveur le pseudo choisis par l'internaute ainsi que sa room. Dans notre cas, on ne fait rien quand le client se connecte. On va attendre qu'il soit "initialisé" avec son nom et qu'il est défini sa room pour en informer les autres clients. Nous utiliserons alors la fonction déclarée sendToAll().

Pour gérer les room, nous allons mémoriser dans chaque objet client du serveur, la room dans laquelle il se trouve. Nous enverrons alors les messages aux clients se trouvant dans la même room. Nous allons donc commencer par modifier la fonction sendToAll() afin que l'on puisse aussi lui indiquer la room dans laquelle seul les clients peuvent recevoir des messages. Notez aussi que nous devons envisager la possibilité d'envoyer des messages à tous les clients sans spécifier de room. D'autre part, nous n'envoyons des messages aux clients que s'ils sont "initialisés" :

Code:
function sendToAll($sauf,$msg,$room){
global $clients;

for($i=0;$i<count($clients);$i++){ // pour tous les clients sauf celui qui envoie
if($sauf!=$clients[$i]["UID"] && ($room==$clients[$i]["ROOM"] || $room==null) && $clients[$i]["INIT"]){
socket_write($clients[$i]["SOCKET"],$msg.chr(0));
}
}
}

Il nous faut également une fonction indiquant aux clients les rooms actuellements ouvertes avec le nombre d'internautes dedans :

Code:
function sendRoomList(){
global $clients;
$memoire=Array();

for($i=0;$i<count($clients);$i++){ // pour tous les clients sauf celui qui envoie
if($clients[$i]["INIT"]){
if($memoire[$clients[$i]["ROOM"]]){
$memoire[$clients[$i]["ROOM"]]++;
}else{
$memoire[$clients[$i]["ROOM"]]=1;
}
}
}
$message="ROOMLIST";
foreach($memoire as $nom => $nbc){
$message.="=".$nom.",".$nbc;
}
sendToAll(null,$message,null);
}

Une foie que l'on a construit notre message, nous l'envoyons à tous les clients de toutes les room. De même, il nous faut une

fonction indiquant aux clients la liste de ceux qui se trouve dans leur room :

Code:
function sendUserList($room){
global $clients;

$message="USERLIST";
for($i=0;$i<count($clients);$i++){ // pour tous les clients sauf celui qui envoie
if($clients[$i]["INIT"] && $clients[$i]["ROOM"]==$room){
$message.="=".$clients[$i]["PSEUDO"].",".$clients[$i]["COLOR"];
}
}
sendToAll(null,$message,$room);
}

Une fois que l'on a construit notre message, nous l'envoyons à tous les clients de cette room.

Nous allons donc traiter les messages des clients. Chaque client nous envoie un message quand il s'initialise, change de room ou quand il chat. Nous allons décomposer cette variable afin d'en connaître les composants et tester de quelle action il s'agit :

Code:
$comp=split("=", $input);
if($comp[0]=="INIT"){
}else if($comp[0]=="SETROOM"){
}else if($comp[0]=="MSG"){
}



Nous avons ici un léger problème. Comme expliqué dans ce post , flash utilise un byte 0 pour terminer ses messages. Ce caractère de fin se retrouve donc dans notre variable $input. D'une manière générale, nous allons retirer tous caractères de fin envoyé par les clients. Pour cela nous allons utiliser la fonction php trim() :

Code:
$input=trim($input);
$comp=split("=", $input);
if($comp[0]=="INIT"){
}else if($comp[0]=="SETROOM"){
}else if($comp[0]=="MSG"){
}


Il ne nous reste plus qu'a traiter chaque action. L'action "INIT" doit mémoriser les données dans les variables du client. L'action "SETROOM" doit changer le nom de la room dans l'objet client, ré envoyer la liste des utilisateurs connectés à son ancienne room (seulement s'il était dans une room), transmettre la liste des clients connectés à tous ceux de cette nouvelle room, transmettre à tous les clients la liste des room ouvertes avec leur nombre de connectés. L'action "MSG" doit simplement envoyer le message aux clients de même room.


Code:
$input=trim($input);
$comp=split("=", $input);
if($comp[0]=="INIT"){
$clients[$i]["INIT"]=true; // on mémorise que ce client est initialisé
$clients[$i]["COLOR"]=$comp[1];
$clients[$i]["PSEUDO"]=$comp[2];
}else if($comp[0]=="SETROOM"){
//// on informe ceux de l'ancienne room
$ancienne=$clients[$i]["ROOM"];
$clients[$i]["ROOM"]=$comp[1];
if($ancienne){
sendUserList($ancienne);
}
//// on informe ceux de la nouvelle room
sendUserList($comp[1]);
//// on informe tous le monde des room ouvertes
sendRoomList();
}else if($comp[0]=="MSG"){
sendToAll($clients[$i]["UID"],"MSG=".$clients[$i]["PSEUDO"].">".$comp[1]."=".$clients[$i]["COLOR"],$clients[$i]["ROOM"]);
}


Nous devons aussi penser à informer tous les clients si l'un d'entre nous se déconnecte. Donc dans la zone "Perte d'un client" nous placerons le code qui permet d'envoyer l'information à ceux de la room du client que quelqu'un est partit. Nous mettons aussi à jour la liste des room ouvertes :

Code:

$clients[$i]["INIT"]=false; // pour ne plus lui envoyer de message
sendUserList($clients[$i]["ROOM"]);
sendRoomList();



Le code du serveur est donc :

Code:
<?php
$mainsock
= socket_create(AF_INET, SOCK_STREAM, 0);
socket_set_option($mainsock, SOL_SOCKET,SO_REUSEADDR, 1);
socket_bind($mainsock, "127.0.0.1", 22222) or die('Could not bind to address');
socket_listen($mainsock);
///////////////////

$clients=Array();
$compteur=0;
echo(
"En attente d'un client !\n");



while(
true){
$toread=Array();
array_push($toread,$mainsock);
for ($i=0;$i<count($clients);$i++){ // pour tous les clients
array_push($toread,$clients[$i]["SOCKET"]);
}

socket_select($toread,$a=null,$a=null,$a=null);

if(in_array($mainsock, $toread)){// le mainsock est dans le tableau $toread.
// c'est notre mainsock donc un nouveau client
$sock=socket_accept($mainsock);
echo("Arrivée d'un nouveau client !\n");
$compteur++;
$nb=count($clients);
$clients[$nb]["SOCKET"]=$sock;
$clients[$nb]["UID"]=$compteur;
}else{
// c'est un client qui dit quelque chose
for ($i=0;$i<count($clients);$i++){ // on cherche le client
if(in_array($clients[$i]["SOCKET"], $toread)) { // celui la est dans le tableau toread
$input = socket_read($clients[$i]["SOCKET"], 1024);
if($input==null){
/// deconnection du client !
for ($j=0;$j<count($clients);$j++){ // on le cherche dans le tableau
if($clients[$j]==$clients[$i]){ // trouvé
//////////////////////////////////////////////////Perte d'un client

$clients[$i]["INIT"]=false; // pour ne plus lui envoyer de message
sendUserList($clients[$i]["ROOM"]);
sendRoomList();

//////////////////////////////////////////////////
echo("Deconnection du client ".$clients[$j]["UID"]."\n");
array_splice($clients,$j,1); // on le retire du tableau
$i--;
}
}
}else{
//////////////////////////////////////////////////Message d'un client
$input=trim($input);
$comp=split("=", $input);
if($comp[0]=="INIT"){
$clients[$i]["INIT"]=true; // on mémorise que ce client est initialisé
$clients[$i]["COLOR"]=$comp[1];
$clients[$i]["PSEUDO"]=$comp[2];
}else if($comp[0]=="SETROOM"){
//// on informe ceux de l'ancienne room
$ancienne=$clients[$i]["ROOM"];
$clients[$i]["ROOM"]=$comp[1];
if($ancienne){
sendUserList($ancienne);
}
//// on informe ceux de la nouvelle room
sendUserList($comp[1]);
//// on informe tous le monde des room ouvertes
sendRoomList();
}else if($comp[0]=="MSG"){ sendToAll($clients[$i]["UID"],"MSG=".$clients[$i]["PSEUDO"].">".$comp[1]."=".$clients[$i]["COLOR"],$clients[$i]["ROOM"]);
}
//////////////////////////////////////////////////
}
}
}
}
}
function
sendToAll($sauf,$msg,$room){
global $clients;

for($i=0;$i<count($clients);$i++){ // pour tous les clients sauf celui qui envoie
if($sauf!=$clients[$i]["UID"] && ($room==$clients[$i]["ROOM"] || $room==null) && $clients[$i]["INIT"]){
socket_write($clients[$i]["SOCKET"],$msg.chr(0));
}
}
}
function
sendRoomList(){
global $clients;
$memoire=Array();

for($i=0;$i<count($clients);$i++){ // pour tous les clients sauf celui qui envoie
if($clients[$i]["INIT"]){
if($memoire[$clients[$i]["ROOM"]]){
$memoire[$clients[$i]["ROOM"]]++;
}else{
$memoire[$clients[$i]["ROOM"]]=1;
}
}
}
$message="ROOMLIST";
foreach($memoire as $nom => $nbc){
$message.="=".$nom.",".$nbc;
}
sendToAll(null,$message,null);
}
function
sendUserList($room){
global $clients;

$message="USERLIST";
for($i=0;$i<count($clients);$i++){ // pour tous les clients sauf celui qui envoie
if($clients[$i]["INIT"] && $clients[$i]["ROOM"]==$room){
$message.="=".$clients[$i]["PSEUDO"].",".$clients[$i]["COLOR"];
}
}
sendToAll(null,$message,$room);
}
php?>



A ce stade le serveur est prêt. Nous allons maintenant nous occuper du client flash. Pour faire simple, nous utiliserons deux images clés. Le première contiendra le code de la gestion socket et l'interface de sélection du pseudo. La seconde, le code des éléments graphiques du chat (ceux-ci n'étant pas présents sur la première clé, on ne peut leur donner des actions) et tous ces champs dynamiques. Nous allons reprendre le code de ce tutorial :

Code:
stop();
var socket = new XMLSocket()
socket.connect("127.0.0.1", 22222)
socket.onConnect = function(success){
}
socket.onData=function(msg){
}

Vous trouverez le fla (fla_etape_1.fla) à cette étape avec les éléments graphiques déjà nommés et installés en bas de la page.

Nous allons indiquer dans le onConnect() si la connection s'est bien effectuée ou non :

Code:
socket.onConnect = function(success){
if(success){
txt_info.text="Connecté sur le port 22222 !"
}else{
txt_info.text="Impossible de se connecter au port 22222 !";
}
}

De la même façon, nous allons alerter l'internaute si la connection est perdue :

Code:
socket.onClose = function(){
txt_info.text="Connection perdue !"
}

Nous allons déterminer la couleur de texte de ce client. Nous utiliserons la fonction random(). La couleur doit être au format hexadécimal, c'est pour cette raison que nous utilisons la fonction toString(16) :

Code:
var selfColor=random(255).toString(16)+random(255).toString(16)+random(255).toString(16);


Dans un premier temps, l'internaute doit choisir son pseudo. Nous allons alors directement programmer l'évènement de validation. Quand l'internaute clique sur "Entrer", il faut tester q'il ait bien tapé quelque chose dans le champ de texte. Si c'est le cas, on demande au serveur de l'initialiser, on part à la clé suivante et on défini sa room (déjà définie dans le champ de texte) :


Code:
bt_valide.onRelease=function(){
if(txt_pseudo.text.length>0){
socket.send("INIT="+selfColor+"="+escape(txt_pseudo.text))
nextFrame();
socket.send("SETROOM="+escape(txt_salon.text))
}
}

Notez la présence de la fonction escape(). Imaginez ce qui se passe si le client désire se nommer "=-moi-=". Le signe "=" du pseudo entrerait en conflit avec notre signe "=" choisis pour séparer les variables. Ainsi on est sur que le message est toujours bien formaté.

Maintenant que nous sommes sur la seconde clé du fla, nous allons donner la possibilité aux clients de chatter. Rappel : le serveur ne nous renvoie pas nos propres messages. Il faut donc penser à ajouter notre texte nous même. Seulement, le champ de texte est au format html. Il y'aura donc un bug si l'on envoie un caractère comme "<" ou "&". Nous allons donc écrire une fonction parseHtml() sur la première image clé qui permettra de nettoyer le texte afin de bien l'afficher. Le plus simple est de couper le texte en tableau et de le reconstituer avec les bons caractères :

Code:
function parseHtml(msg){
var tab=msg.split("&");
msg=tab.join("&amp;");
var tab=msg.split("<");
msg=tab.join("&lt;");
return msg;
}

Notre action de boutons est donc :

Code:
bt_send.onRelease=function(){
if(txt_message.text.length){
socket.send("MSG="+escape(txt_message.htmlText));
txt_message.htmlText=""
txt_ecran.htmlText+="<font color='"+selfColor+"'>"+txt_message.htmlText+"</font>"
txt_ecran.scroll=txt_ecran.maxscroll;
}
}

Toujours sur la clé deux, l'internaute peut choisir de changer de room. Ce changement sera détecté grâce à la méthode onChanged() du champs de texte txt_salon. Quand on change de room, on en avertit le serveur qui nous renvoies toutes les nouvelles données :

Code:
txt_salon.onChanged=function(){
socket.send("SETROOM="+escape(this.text));
}

Nous allons maintenant nous occuper de ce que le serveur nous envoie. Comme pour le serveur, il nous faut d'abord décomposer le message afin d'en connaître l'action :

Code:
socket.onData=function(msg){
var comp=msg.split("=");
if(comp[0]=="ROOMLIST"){
}else if(comp[0]=="USERLIST"){
}else if(comp[0]=="MSG"){
}
}

Premièrement l'action "ROOMLIST". Le serveur nous donne donc la liste de toutes les room ouvertes avec le nombre de connectés. Nous allons faire en sorte que l'on puisse cliquer sur la room pour y entrer directement. Pour cela, ce champs de texte doit être au format html. Nous y placerons le tag "<A HREF='asfunction:func,param'>" pour appeler une fonction quand on y clique dessus. Nous allons donc écrire cette fonction :

Code:
function clickRoom(room){
txt_salon.text=unescape(nom)
socket.send("SETROOM="+this.text);
}

Ici, pas besoin de fonction escape() puisque le paramètre sera déjà parsé dans le tag html. Ne reste plus qu'a remplir notre champ de texte txt_room grâce aux informations du serveur dans l'action "ROOMLIST". Ces informations sont au format : "room,nombre". Nous devons donc décomposer chaque paramètres :

Code:
txt_room.htmlText="";
for(var i=1;i<comp.length;i++){
var detail=comp[i].split(",");
txt_room.htmlText+="<A HREF='asfunction:clickRoom,"+detail[0]+"'><U>"+parseHtml(unescape(detail[0]))+"

("+detail[1]+")</U></A><br>";

}


Remarquez ici la présence de la fonction unescape(). Souvenez-vous que pour être sur que le choix hasardeux du pseudo ou de la room d'un client ne perturbe pas le format de nos messages, nous utilisions la fonction escape(). Pour récupérer le texte au bon format, nous utilisons donc l'inverse qui est bien unescape().

Nous allons faire pareil pour l'action "USERLIST" mais sans se préoccuper du tag "<A HREF>". En revanche, il faut le mettre à la bonne couleur :

Code:
txt_user.htmlText="";
for(var i=1;i<comp.length;i++){
var detail=comp[i].split(",");
txt_user.htmlText+="<FONT COLOR='#"+detail[1]+"'>"+parseHtml(unescape(detail[0]))+"</font><br>";

}

Ne reste plus qu'à traiter l'action "MSG" avec la bonne couleur :

Code:
txt_ecran+="<FONT COLOR='#"+comp[2]+"'>"+parseHtml(unescape(comp[1]))+"</FONT><br>";
txt_ecran.scroll=txt_ecran.maxscroll;

Notre gestion de réceptions de données deviens alors :

Code:
socket.onData=function(msg){
var comp=msg.split("=");
if(comp[0]=="ROOMLIST"){
txt_room.htmlText="";
for(var i=1;i<comp.length;i++){
var detail=comp[i].split(",");
txt_room.htmlText+="<A HREF='asfunction:clickRoom,"+detail[0]+"'><U>"+parseHtml(unescape(detail[0]))+" ("+detail[1]+")</U></A><BR>";
}
}else if(comp[0]=="USERLIST"){
txt_user.htmlText="";
for(var i=1;i<comp.length;i++){
var detail=comp[i].split(",");
txt_user.htmlText+="<FONT COLOR='#"+detail[1]+"'>"+parseHtml(unescape(detail[0]))+"</font><br>";
}
}else if(comp[0]=="MSG"){
txt_ecran.htmlText+="<FONT COLOR='#"+comp[2]+"'>"+parseHtml(unescape(comp[1]))+"</FONT><br>";
txt_ecran.scroll=txt_ecran.maxscroll;
}
}

Et voila :-)

Au final, le code sur la première clé ressemble à ceci :

Code:
stop();
var socket = new XMLSocket()
var selfColor=random(255).toString(16)+random(255).toString(16)+random(255).toString(16);
socket.connect("127.0.0.1", 22222)
socket.onConnect = function(success){
if(success){
txt_info.text="Connecté sur le port 12000 !"
}else{
txt_info.text="Impossible de se connecter au port 12000 !";
}
}
socket.onClose = function(){
txt_info.text="Connection perdue !"
}
bt_valide.onRelease=function(){
if(txt_pseudo.text.length>0){
socket.send("INIT="+selfColor+"="+escape(txt_pseudo.text))
nextFrame();
socket.send("SETROOM="+escape(txt_salon.text))
}
}
socket.onData=function(msg){
trace(msg)
var comp=msg.split("=");
if(comp[0]=="ROOMLIST"){
txt_room.htmlText="";
for(var i=1;i<comp.length;i++){
var detail=comp[i].split(",");
txt_room.htmlText+="<A HREF='asfunction:clickRoom,"+detail[0]+"'><U>"+parseHtml(unescape(detail[0]))+" ("+detail[1]+")</U></A><BR>";
}
}else if(comp[0]=="USERLIST"){
txt_user.htmlText="";
for(var i=1;i<comp.length;i++){
var detail=comp[i].split(",");
txt_user.htmlText+="<FONT COLOR='#"+detail[1]+"'>"+parseHtml(unescape(detail[0]))+"</font><br>";
}
}else if(comp[0]=="MSG"){
txt_ecran.htmlText+="<FONT COLOR='#"+comp[2]+"'>"+parseHtml(unescape(comp[1]))+"</FONT><br>";
txt_ecran.scroll=txt_ecran.maxscroll;
}
}
function parseHtml(msg){
var tab=msg.split("&");
msg=tab.join("&amp;");
var tab=msg.split("<");
msg=tab.join("&lt;");
return msg;
}
function clickRoom(nom){
txt_salon.text=unescape(nom)
socket.send("SETROOM="+nom);
}

Celui de la seconde :

Code:
bt_send.onRelease=function(){
if(txt_message.text.length){
socket.send("MSG="+escape(txt_message.htmlText));
txt_ecran.htmlText+="<font color='#"+selfColor+"'>"+txt_message.htmlText+"</font>"
txt_ecran.scroll=txt_ecran.maxscroll;
txt_message.htmlText=""
}
}
txt_salon.onChanged=function(){
socket.send("SETROOM="+escape(this.text));
}


Vous pouvez télécharger le fla (fla_etape_2.fla) ou directement observer le résultat de ce tutorial en ligne.




* fla_etape_1.fla (48 KB - Téléchargé 547 fois.)
* serveur_php4.php (3.76 KB - Téléchargé 595 fois.)
* serveur_perl.pl (3.4 KB - Téléchargé 392 fois.)
* fla_etape_2.fla (59 KB - Téléchargé 684 fois.)
« Dernière édition: Août 22, 2005, 05:34:54 par seal3 » Journalisée

Ma signature utilise un compte your-socket afin de dessiner/chatter en temps réel. Etant aussi sur media-box vous y trouverez aussi leurs membres Smiley.
<a href="http://ystutori.your-socket.com/mediabox/dessin.swf" target="_blank">http://ystutori.your-socket.com/mediabox/dessin.swf</a>
seal3
Administrator
Hero Member
*****
Messages: 504


Voir le profil
Re: Chat multi-room
« Répondre #1 le: Novembre 14, 2005, 11:32:12 »

YSServer v1.0

Nous allons réécrire la partie serveur en réalisant une application pour YSServer v1.0. Pour plus d'informations sur YSServer cliquez ici. Nous allons démarrer d'un script php de base prêt à l'emploi :

Code:
<?php
function onNewClient($uid){
}
function
onLostClient($uid){
}
function
onClientMessage($uid,$msg){
}
?>


Pour cette application nous allons avoir besoin de mémoriser les informations des clients. Il nous faut donc un tableau "$clientList" et utiliser "global" pour pouvoir l'utiliser dans les fonctions. L'ors qu'un client se connecte ou se déconnecte, il nous faudra ajouter/retirer le client du tableau. Un client possédera plusieurs données, il faudra donc créer un tableau pour chaque nouveau clients. Ce qui nous donne :

Code:
<?php
$clientList
=array();
function
onNewClient($uid){
global $clientList;
$clientList[$uid]=array();
}
function
onLostClient($uid){
global $clientList;
unset($clientList[$uid]);
}
function
onClientMessage($uid,$msg){
global $clientList;
}
?>


Comme dans le post ci-dessus, nous allons traiter les messages reçus par le serveur en les découpant :

Code:
function onClientMessage($uid,$msg){
global $clientList;
$comp=split("=",$msg);
if($comp[0]=="INIT"){
}else if($comp[0]=="MSG"){
}else if($comp[0]=="SETROOM"){
}
}

Nous utiliserons les "personalData" du YSServer pour définir le pseudo et la couleur de chaque client et ainsi pouvoir les transmettre rapidement à tous les autres. A l'initialisation il nous faut donc enregistrer les personalData et enregistrer les paramètres du client dans le tableau :

Code:
function onClientMessage($uid,$msg){
global $clientList;
$comp=split("=",$msg);
if($comp[0]=="INIT"){
setPersonalData($comp[2].",".$comp[1],$uid);
$clientList[$uid]["PSEUDO"]=$comp[2];
$clientList[$uid]["COLOR"]=$comp[1];
}else if($comp[0]=="MSG"){
}else if($comp[0]=="SETROOM"){
}
}

La première ligne définie les données personnelles du client $uid.
La seconde et la troisième mémorisent les valeurs dans le tableau du client.

Quand le client tchat, nous devons définir à qui le message doit partir. Nous utiliserons la fonction sendMessage et son FiltreClient pour envoyer le message à tous ceux du même groupe que l'émetteur sauf lui même :

Code:
sendMessage("MSG=".$clientList[$uid]["PSEUDO"].">".$comp[1]."=".$clientList[$uid]["COLOR"],"[".$uid."] && !$uid");

Consultez l'aide du YSServer pour comprendre le filtre :  "[".$uid."] && !$uid".

Maintenant, le changement de room : Ce changement se fait en 4 étapes :

1) Envoyer la liste de tous les clients sauf nous même au groupe que l'on quitte pour que tous ceux que l'on laisse reçoivent la nouvelle liste.

2) Changer de groupe

3) Envoyer la nouvelle liste de client au groupe que l'on vient de rejoindre.

4) Envoyez la mise à jour des groupes à tous le monde.


Ce qui nous donne :

Code:
function onClientMessage($uid,$msg){
global $clientList;
$comp=split("=",$msg);
if($comp[0]=="INIT"){
setPersonalData($comp[2].",".$comp[1],$uid);
$clientList[$uid]["PSEUDO"]=$comp[2];
$clientList[$uid]["COLOR"]=$comp[1];
}else if($comp[0]=="MSG"){
sendMessage("MSG=".$clientList[$uid]["PSEUDO"].">".$comp[1]."=".$clientList[$uid]["COLOR"],"[".$uid."] && !$uid");
}else if($comp[0]=="SETROOM"){
        sharePersonalData("USERLIST=","[".$uid."] && !".$uid,"[".$uid."] && !".$uid,"=");
        removeClientGroup($uid,$uid);
        addClientGroup($comp[1],$uid);
        sharePersonalData("USERLIST=","[".$uid."]","[".$uid."]","=");
sendGroupCount("ROOMLIST=","","",",","=",false);
}
}

Ne reste plus qu'à gérer la déconnection d'un client en renvoyant la liste de tous les clients au groupe dans lequel nous étions ainsi que la liste de tous les groupes. Notre code final devient :


Code:
<?php
$clientList
=array();
function
onNewClient($uid){
global $clientList;
$clientList[$uid]=array();
}
function
onLostClient($uid){
global $clientList;
unset($clientList[$uid]);
        
sharePersonalData("USERLIST=","[".$uid."] && !".$uid,"[".$uid."]","=");
sendGroupCount("ROOMLIST=","!".$uid,"",",","=",false);
}
function
onClientMessage($uid,$msg){
global $clientList;
$comp=split("=",$msg);
if($comp[0]=="INIT"){
setPersonalData($comp[2].",".$comp[1],$uid);
$clientList[$uid]["PSEUDO"]=$comp[2];
$clientList[$uid]["COLOR"]=$comp[1];
}else if($comp[0]=="MSG"){
sendMessage("MSG=".$clientList[$uid]["PSEUDO"].">".$comp[1]."=".$clientList[$uid]["COLOR"],"[".$uid."] && !$uid");
}else if($comp[0]=="SETROOM"){
        sharePersonalData("USERLIST=","[".$uid."] && !".$uid,"[".$uid."] && !".$uid,"=");
        removeClientGroup($uid,$uid);
        addClientGroup($comp[1],$uid);
        sharePersonalData("USERLIST=","[".$uid."]","[".$uid."]","=");
sendGroupCount("ROOMLIST=","","",",","=",false);
}
}
?>


Vous trouverez les applications au format PHP et PERL en bas de la page mais également dans le pack libre de téléchargement.

* appli.php (1.03 KB - Téléchargé 426 fois.)
* appli.pl (0.99 KB - Téléchargé 242 fois.)
Journalisée

Ma signature utilise un compte your-socket afin de dessiner/chatter en temps réel. Etant aussi sur media-box vous y trouverez aussi leurs membres Smiley.
<a href="http://ystutori.your-socket.com/mediabox/dessin.swf" target="_blank">http://ystutori.your-socket.com/mediabox/dessin.swf</a>
Pages: [1] Imprimer 
« sujet précédent | | sujet suivant »
Aller à:  

Propulsé par MySQL Propulsé par PHP your-socket | Propulsé par SMF 1.0.5.
© 2001-2004, Lewis Media. Tous droits réservés.
XHTML 1.0 Transitionnel valide! CSS valide!

serveurs de sockets en java,perl,php,c++
serveurs de sockets en java,perl,php,c++