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++
Dessin à plusieurs
your-socket
Bienvenue, Invité. Veuillez vous connecter ou vous enregistrer.
Avez-vous perdu votre courriel d'activation?Bienvenue.
Septembre 04, 2010, 10:53:34

Connexion avec identifiant, mot de passe et durée de la session
Recherche:     Recherche +
Lancement du YSServer
1150 Messages dans 138 Sujets par 9690 Membres
Dernier membre: semiaddict
* Accueil Aide Recherche Identifiez-vous Enregistrez-vous
+  your-socket
|-+  Tutoriaux
| |-+  Niveau 2
| | |-+  Dessin à plusieurs
« sujet précédent | | sujet suivant »
Pages: [1] Imprimer
Auteur Sujet: Dessin à plusieurs  (Lu 2514 fois)
seal3
Administrator
Hero Member
*****
Messages: 504


Voir le profil
Dessin à plusieurs
« le: Août 20, 2005, 03:36:25 »

Dans ce tutorial, nous allons créer une application multi-utilisateurs permettant de dessiner à plusieurs sur un tableau.

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;
//////////////////////////////////////////////////Arrivée d'un client



//////////////////////////////////////////////////
}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 trois zones dans lesquelles nous allons travailler. Ces trois zones représentent respectivement : la gestion d'arrivée d'un client, de déconnection et de réception de message.

L'ors q'un client se connecte, nous allons transmettre à tous le monde le nombre total de clients connectés. Pour cela nous allons utiliser la fonction déclarée sendToAll() mais sans y passer le numéro de client qu'il faut éviter. En effet le client qui viens de se connecter doit aussi connaître le nombre total de users. Nous ajouterons donc la ligne suivante dans la première zone (Arrivée d'un client) :

Code:
sendToAll(null,"NBUSER=".count($clients));



Il nous faut faire la même chose si un client se déconnecte. En revanche, ici nous indiquerons à la fonction sendToAll() qu'il ne faut pas envoyer le message au client qui s'est déconnecté. Nous ajouterons donc la ligne suivante :

Code:
sendToAll($clients[$i]["UID"],"NBUSER=".(count($clients)-1));


Nous allons maintenant traiter le message des clients. Chaque client nous envoie un message quand il faut dessiner une ligne sur notre tableau, l'effacer etc... Pour faire la distinction entre chaque commande, chaque message d'un client serra composé de l'action à faire suivie par des paramètres et le tout séparé par un caractère spécial (nous choisissons le signe "=").

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 :

SETCOLOR=1256
C'est au démarrage du swf que nous déciderons de la couleur. Le client transmettra donc sa couleur au serveur. Ainsi, plus tard, le client n'aura qu'a envoyer les informations de positions pour dessiner la ligne sans envoyer la couleur. On y gagne en bande passante et en rapidité (même si dans ce cas, c'est franchement négligeable).

CLEAR
Ici un client demande d'effacer le tableau.

LINE=10=20=100=100
Un client viens de dessiner une ligne. Les deux premiers paramètres correspondent au premier point de la ligne en x et y, les deux suivants correspondent au second point en x et y.

Le message du client se trouve donc dans la variable $input. 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]=="SETCOLOR"){
}else if($comp[0]=="CLEAR"){
}else if($comp[0]=="LINE"){
}



Nous avons ici un léger problème. Comme expliqué dans ce post , flash utilise un byte 0 pour terminer ses messages. Donc le message d'effacement du tableau sera équivalent à "CLEAR".chr(0)
Du coup notre "if" ne sera pas validé puisque il teste un simple "CLEAR". 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]=="SETCOLOR"){
}else if($comp[0]=="CLEAR"){
}else if($comp[0]=="LINE"){
}


Il ne nous reste plus qu'a traiter chaque action.


Code:
$input=trim($input);
$comp=split("=", $input);
if($comp[0]=="SETCOLOR"){
$clients[$i]["COLOR"]=$comp[1];
}else if($comp[0]=="CLEAR"){
sendToAll($clients[$i]["UID"],"CLEAR");
}else if($comp[0]=="LINE"){
sendToAll($clients[$i]["UID"],"LINE=".$comp[1]."=".$comp[2]."=".$comp[3]."=".$comp[4]."=".$clients[$i]["COLOR"]);
}


Dans l'action SETCOLOR nous nous contentons de définir la variable "COLOR" du client. Pour les autres actions, nous envoyons les messages aux autres clients. Pour l'action LINE, nous reconstituons le message afin d'ajouter à la fin la couleur du client qui envoie la commande.

Il y'a ici de nombreuses façons de procéder : Nous pourrions informer chaque clients de la couleur de tous les autres une fois pour toutes dès le début afin de ne plus s'en préoccuper côté serveur. Nous pourrions aussi transmettre la couleur directement dans le message du client qui demande à dessiner une ligne, mais cela ferait des messages plus long et plus gourmands en bande passante.

Le code 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;
//////////////////////////////////////////////////Arrivée d'un client

sendToAll(null,"NBUSER=".count($clients));

//////////////////////////////////////////////////
}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

sendToAll($clients[$i]["UID"],"NBUSER=".(count($clients)-1));

//////////////////////////////////////////////////
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]=="SETCOLOR"){
$clients[$i]["COLOR"]=$comp[1];
}else if($comp[0]=="CLEAR"){
sendToAll($clients[$i]["UID"],"CLEAR");
}else if($comp[0]=="LINE"){
sendToAll($clients[$i]["UID"],"LINE=".$comp[1]."=".$comp[2]."=".$comp[3]."=".$comp[4]."=".$clients[$i]["COLOR"]);
}
//////////////////////////////////////////////////
}
}
}
}
}


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?>



A ce stade le serveur est prêt. Nous allons maintenant nous occuper du client flash. Nous allons reprendre le code de ce tutorial :

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

Nous allons aussi installer les éléments sur la scène :

Une zone de dessin nommée "tableau".
Un bouton effacé nommée "bt_clear".
Un champ de texte dynamique pour afficher le résultat de connection nommée "txt_info".
Un champ de texte dynamique pour afficher le nombre de connectés nommée "txt_nbcon".

Vous trouverez le fla (fla_etape_1.fla) à cette étape 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 ce client. Nous utiliserons la fonction random() :

Code:
var selfColor=random(0xFFFFFF);

Quand le client se connecte, il doit informer le serveur de sa couleur :

Code:
var selfColor=random(0xFFFFFF);
socket.onConnect = function(success){
if(success){
socket.send("SETCOLOR="+selfColor);
txt_info.text="Connecté sur le port 22222 !"
}else{
txt_info.text="Impossible de se connecter au port 22222 !";
}
}

Nous allons gérer la commande "CLEAR" :

Code:
bt_clear.onRelease=function(){
socket.send("CLEAR");
tableau.clear();
}


Maintenant nous allons donner la possibilité au client de dessiner. Pour cela, quand on clique sur le tableau, il faut initialiser un gestionnaire "onEnterFrame()" et mémoriser la position du click. Dans le "onEnterFrame", on dessine la ligne, informe le serveur et modifie la valeur X et Y du premier point. Quand on relâche la souris, on stoppe le gestionnaire "onEnterFrame()" :

Code:
tableau.onPress=function(){
Xpos=this._xmouse;
Ypos=this._ymouse;
onEnterFrame=function(){
tableau.lineStyle(2,selfColor,100)
tableau.moveTo(Xpos,Ypos);
tableau.lineTo(tableau._xmouse,tableau._ymouse);
socket.send("LINE="+Xpos+"="+Ypos+"="+tableau._xmouse+"="+tableau._ymouse)
Xpos=tableau._xmouse;
Ypos=tableau._ymouse;
}
}
tableau.onRelease=tableau.onReleaseOutside=function(){
delete onEnterFrame;
}


Le code de la première clé du fla est maintenant :

Code:
var socket = new XMLSocket()
var selfColor=random(0xFFFFFF);

socket.connect("127.0.0.1", 22222)
socket.onClose = function(){
txt_info.text="Connection perdue !"
}
socket.onConnect = function(success){
if(success){
socket.send("SETCOLOR="+selfColor);
txt_info.text="Connecté sur le port 22222 !"
}else{
txt_info.text="Impossible de se connecter au port 22222 !";
}
}
socket.onData=function(msg){
}
bt_clear.onRelease=function(){
socket.send("CLEAR");
tableau.clear()
}
tableau.onPress=function(){
Xpos=this._xmouse;
Ypos=this._ymouse;
onEnterFrame=function(){
tableau.lineStyle(2,selfColor,100)
tableau.moveTo(Xpos,Ypos);
tableau.lineTo(tableau._xmouse,tableau._ymouse);
socket.send("LINE="+Xpos+"="+Ypos+"="+tableau._xmouse+"="+tableau._ymouse)
Xpos=tableau._xmouse;
Ypos=tableau._ymouse;
}
}
tableau.onRelease=tableau.onReleaseOutside=function(){
delete onEnterFrame
}

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]=="CLEAR"){
}else if(comp[0]=="LINE"){
}else if(comp[0]=="NBUSER"){
}
}

Maintenant, chaque action :


Code:
socket.onData=function(msg){
var comp=msg.split("=");
if(comp[0]=="CLEAR"){
tableau.clear();
}else if(comp[0]=="LINE"){
tableau.lineStyle(2,comp[5],100);
tableau.moveTo(comp[1],comp[2]);
tableau.lineTo(comp[3],comp[4]);
}else if(comp[0]=="NBUSER"){
txt_nbcon.text=comp[1]+" connectés";
}
}

Et voila :-)

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

Code:
var socket = new XMLSocket()
var selfColor=random(0xFFFFFF);

socket.connect("127.0.0.1", 22222)
socket.onClose = function(){
txt_info.text="Connection perdue !"
}
socket.onConnect = function(success){
if(success){
socket.send("SETCOLOR="+selfColor);
txt_info.text="Connecté sur le port 22222 !"
}else{
txt_info.text="Impossible de se connecter au port 22222 !";
}
}
socket.onData=function(msg){
trace(msg)
var comp=msg.split("=");
if(comp[0]=="CLEAR"){
tableau.clear();
}else if(comp[0]=="LINE"){
tableau.lineStyle(2,comp[5],100);
tableau.moveTo(comp[1],comp[2]);
tableau.lineTo(comp[3],comp[4]);
}else if(comp[0]=="NBUSER"){
txt_nbcon.text=comp[1]+" connecté(s)";
}
}
bt_clear.onRelease=function(){
socket.send("CLEAR");
tableau.clear()
}
tableau.onPress=function(){
Xpos=this._xmouse;
Ypos=this._ymouse;
onEnterFrame=function(){
tableau.lineStyle(2,selfColor,100)
tableau.moveTo(Xpos,Ypos);
tableau.lineTo(tableau._xmouse,tableau._ymouse);
socket.send("LINE="+Xpos+"="+Ypos+"="+tableau._xmouse+"="+tableau._ymouse)
Xpos=tableau._xmouse;
Ypos=tableau._ymouse;
}
}
tableau.onRelease=tableau.onReleaseOutside=function(){
delete onEnterFrame
}


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




* fla_etape_1.fla (43.5 KB - Téléchargé 272 fois.)
* fla_etape_2.fla (48 KB - Téléchargé 305 fois.)
* serveur_php4.php (2.61 KB - Téléchargé 283 fois.)
* serveur_perl.pl (2.3 KB - Téléchargé 233 fois.)
« Dernière édition: Août 22, 2005, 11:54:16 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: Dessin à plusieurs
« Répondre #1 le: Novembre 14, 2005, 11:40:10 »

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 la couleur de chaque client. 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. Nous aurons également besoin d'un compteur pour pouvoir afficher le nombre de connections.

A chaque connection/deconnection, nous mettrons le compteur $cmpt à jour et en informerons tous les clients.

Ce qui nous donne :

Code:
<?php
$clientList
=array();
$cmpt=0;
function
onNewClient($uid){
global $clientList,$cmpt;
$clientList[$uid]=array();
$cmpt++;
sendMessage("NBUSER=".$cmpt,"");
}
function
onLostClient($uid){
global $clientList,$cmpt;
$cmpt--;
unset($clientList[$uid]);
sendMessage("NBUSER=".$cmpt,"");
}
function
onClientMessage($uid,$msg){
}
?>



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]=="SETCOLOR"){
}else if($comp[0]=="CLEAR"){
}else if($comp[0]=="LINE"){
}
}

Ne reste plus qu'à remplir :

1) SETCOLOR : mettre à jour le $clientList pour mémoriser la couleur du client.
2) CLEAR : Envoyer à tous le monde l'ordre d'effacer l'écran.
2) LINE : Envoyer à tous le monde l'ordre de dessiner une ligne.

Au final le code est :

Code:
<?php
$clientList
=array();
$cmpt=0;
function
onNewClient($uid){
global $clientList,$cmpt;
$clientList[$uid]=array();
$cmpt++;
sendMessage("NBUSER=".$cmpt,"");
}
function
onLostClient($uid){
global $clientList,$cmpt;
$cmpt--;
unset($clientList[$uid]);
sendMessage("NBUSER=".$cmpt,"");
}
function
onClientMessage($uid,$msg){
global $clientList;
$comp=split("=",$msg);
if($comp[0]=="SETCOLOR"){
$clientList[$uid]["COLOR"]=$comp[1];
}else if($comp[0]=="CLEAR"){
sendMessage("CLEAR","");
}else if($comp[0]=="LINE"){
sendMessage("LINE=".$comp[1]."=".$comp[2]."=".$comp[3]."=".$comp[4]."=".$clientList[$uid]["COLOR"],"!".$uid);
}
}
?>


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 (0.66 KB - Téléchargé 242 fois.)
* appli.pl (0.57 KB - Téléchargé 198 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++