Arriver à déconnecter le dernier client - socket php

  • Auteur de la discussion benoit5699
  • Date de début

benoit5699

Nouveau membre
J'utilise donc ce script php pour faire tourner un chat qui renvoie pour l'instant à chaque utilisateur le nombre de clients connectés.

Bon nouveau problème ce soir...MOn chat fonctionne mieux qu'hier sauf que je voudrait arriver à arrêter le script quand le dernier client s'est déconnecté. Pour cela j'ai rajouté les lignes 64 à 72 à mon sript d'hier.
Lorsque qu'un client se déconnecte ça marche très bien, je fais bien $nbclients-- ce qui me permet de compter mes clients sans soucis. Mais lorsque le dernier se déconnecte, impossible...en effet le "il faut s'en aller" ne s'affiche jamais et ça continue à tourner. Pourquoi ? Est ce que quelqu'un voit ? C'est comme si la déconnexion du dernier ne faisait pas un $input == null...
[cpp]
<?php

// Set time limit to indefinite execution
set_time_limit (0);

// Set the ip and port we will listen on
$address = '127.0.0.1';
$port = 2010;
$max_clients = 10;

// Array that will hold client information
$client = Array();

// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
socket_bind($sock, $address, $port) or die('Could not bind to address');
// Start listening for connections
socket_listen($sock);
$nbclients=0;


// Loop continuously
while (true) {
echo 'je commence une boucle while</br>';
// Setup clients listen socket for reading
$read[0] = $sock;
for ($i = 0; $i < $max_clients; $i++)
{
if ($client[$i]['sock'] != null)
$read[$i + 1] = $client[$i]['sock'] ;
}
// Set up a blocking call to socket_select()
$ready = socket_select($read, $write = NULL, $except = NULL, $tv_sec = NULL);
// if a new connection is being made add it to the client array
if (in_array($sock, $read)) {
for ($i = 0; $i < $max_clients; $i++)
{
if ($client[$i]['sock'] == null) {
$client[$i]['sock'] = socket_accept($sock);
$nbclients++;
break;


}
elseif ($i == $max_clients - 1)
print ("too many clients");
}
if (--$ready <= 0)
continue;
} // end if in_array

// If a client is trying to write - handle it now
for ($i = 0; $i < $max_clients; $i++) // for each client
{
if (in_array($client[$i]['sock'] , $read))
{
$input = socket_read($client[$i]['sock'] , 1024);
if ($input == null) {
// Zero length string meaning disconnected
unset($client[$i]);
if($nbclients==1)
{
echo 'il faut s\'en aller</br>';
socket_close($client[$i]['sock']);
socket_close($sock);
break(2);
}
else
{
$nbclients--;
}

}
$n = trim($input);
if ($input == 'exit') {
// requested disconnect
socket_close($client[$i]['sock']);


} elseif ($input) {
// strip white spaces and write back to user
$output = ereg_replace("[ \t\n\r]","",'<thenodemyData="nbclients : "'.$nbclients.' />').chr(0);
for ($j = 0; $j < $max_clients; $j++) // for each client
{
if ($client[$j]['sock'])
{
socket_write($client[$j]['sock'], $output);
}
}
}
}

}
} // end while
// Close the master sockets

socket_close($sock);

?>

[/cpp]

Merci énormément de votre attention ! Bonne nuit à toutes et à tous !

++

Benoît
 

batchy

Grand Maître
Et si à la ligne 25 tu affiche la valeur de $nbclients, ça donne quoi ?

Moi j'aurai remplacé le while (true) par while(il reste un mec), mais ça devrai quand même marcher comme ça.
 

benoit5699

Nouveau membre
Bah il continue à m'afficher qu'il reste qqun même si j'ai déconnecté tout le monde.

Le pb en fait c'est que il n'entre jamais dans le
[cpp]
# if($nbclients==1)
# {
# echo 'il faut s\'en aller</br>';
# socket_close($client[$i]['sock']);
# socket_close($sock);
# break(2);
# }
[/cpp]

comme si au dernier client ça ne faisait pas input == null pour une déconnexion.

Seule exception où ça se passe bien c'est quand je ne connecte qu'un seul client. Ensuite je le déconnecte. Dans cette configuration le script s'arrête comme je veux.

Mais si j'en connecte 1 puis 2 puis 3 puis que je les déconnecte un par un (peu importe l'ordre) et bien la mon script reste bloqué à 1 et continue à mouliner.

J'avoue que j'ai relu le script 1000 fois et que je bloque complétement ...

Je maintiens le pont d'or pour celui qui trouve parce que sinon je vais continuer les nuits blanches...

Merci de votre attention et bonne soirée !

Benoit
 

batchy

Grand Maître
Quand tu "déconnecte" ton client, tu envoie "exit", ou tu déconnecte à l'arrache en tuant tes clients ?

Car si tu envoie "exit", on déconnecte direct, on décrémente rien, et on laisse l'entrée dans le tableau.

et c'est la qu'on a envie de créer une fonction "virer_client($i)" qui fait tout ça et qu'on appelle quand on reçoit "exit" ou quand on reçoit une déconnexion sauvage ;)
 

benoit5699

Nouveau membre
en fait non je n'utilise pas l'exit. exit c'était dans le code que j'ai récupéré mais moi c'est déconnexion à l'arrache. je vais virer la partie avec exit.
 

benoit5699

Nouveau membre
Voilà le code un peut nettoyé tel que je le fait tourner. J'ai rajouté :
Au début initialisation des $client[$i]['sock']=null sinon ça ma fait des offsets undefined.
Retrait de la partie if input='exit' puisque de toutes façons ce n'est pas comme ça que je déconnecte mes clients.
Au lieu de faire unset(clients[$i]) je fais juste $client[$i]['sock']=null pour évier également des problèmes d'offset...
Mais le problème reste bien là !!
[cpp]
<?php

// Set time limit to indefinite execution
set_time_limit (0);

// Set the ip and port we will listen on
$address = '127.0.0.1';
$port = 2010;
$max_clients = 10;

// Array that will hold client information
$client = Array();

// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
socket_bind($sock, $address, $port) or die('Could not bind to address');
// Start listening for connections
socket_listen($sock);
$nbclients=0;
for ($i = 0; $i < $max_clients; $i++)
{
$client[$i]['sock'] = null;
}

// Loop continuously
while (true) {
echo 'je commence une boucle while et nbclients = '.$nbclients.'</br>';
// Setup clients listen socket for reading
$read[0] = $sock;
for ($i = 0; $i < $max_clients; $i++)
{
if ($client[$i]['sock'] != null)
$read[$i + 1] = $client[$i]['sock'] ;
}
// Set up a blocking call to socket_select()
$ready = socket_select($read, $write = NULL, $except = NULL, $tv_sec = NULL);

// if a new connection is being made add it to the client array
if (in_array($sock, $read)) {
for ($i = 0; $i < $max_clients; $i++)
{
if ($client[$i]['sock'] == null) {
$client[$i]['sock'] = socket_accept($sock);
$nbclients++;
break;


}
elseif ($i == $max_clients - 1)
print ("too many clients");
}
if (--$ready <= 0)
continue;
} // end if in_array

// If a client is trying to write - handle it now
for ($i = 0; $i < $max_clients; $i++) // for each client
{
if (in_array($client[$i]['sock'] , $read))
{
$input = socket_read($client[$i]['sock'] , 1024);
echo 'input = '.$input.'</br>';
if ($input == null) {
// Zero length string meaning disconnected
$client[$i]['sock']=null;
echo 'on enlève un lcient</br>';
if($nbclients==1)
{
$nbclients--;
echo 'il faut s\'en aller</br>';
syslog(LOG_WARNING, 'il faut s\'en aller</br>');
socket_close($client[$i]['sock']);
break(2);
}
else
{
$nbclients--;
}

}

$n = trim($input);
if ($input) {
// strip white spaces and write back to user
$output = ereg_replace("[ \t\n\r]","",'<thenodemyData="nbclients : "'.$nbclients.' />').chr(0);
for ($j = 0; $j < $max_clients; $j++) // for each client
{
if ($client[$j]['sock'])
{
socket_write($client[$j]['sock'], $output);
}
}
}
}

}
} // end while
// Close the master sockets

socket_close($sock);

?>
[/cpp]
 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 131
Messages
6 717 939
Membres
1 586 382
Dernier membre
alejandrooo
Partager cette page
Haut