Comment utiliser sleep () plusieurs fois simultanément dans une boucle ?

Eléphanteau du PHP | 23 Messages

26 févr. 2009, 04:49

Bonjour,

Je ne sais pas si c'est possible de faire quelque chose comme ce qui va suivre : le problème vient de la fonction sleep () que je voudrais lancer simultanément avec différentes valeurs dans différentes fonctions :
<?php

function fonction_1 ()
{
	// fait plein de choses
	sleep ($interval_pour_1)
}

function fonction_2 ()
{
	// fait plein de choses
	sleep ($interval_pour_2)
}

...

function fonction_n ()
{
	// fait plein de choses
	sleep ($interval_pour_n)
}


while ($condition_respectee)
{
	fonction_1()
	fonction_2()
	...
	fonction_n
}

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

26 févr. 2009, 09:42

Bonjour,

Oui c'est possible.
(A part le "simultanément" qui n'est pas possible)
Quand tout le reste a échoué, lisez le mode d'emploi...

Eléphanteau du PHP | 23 Messages

26 févr. 2009, 10:21

Ben justement, c'est ça qui me coince : est-ce qu'il y a un moyen de contourner ?

Peut-être en lançant plusieurs autres scripts PHP simultanéments, qui comprendrait chacun leur propre boucle "while ($condition_verifiee)", mais alors comment lancer ces scripts ? J'ai cru comprendre que la commande exec() était plutôt faite pour des applis extérieures, pas pour des scripts PHP... :cry:

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

26 févr. 2009, 10:50

PHP ne permet pas nativement de faire plusieurs thread en parallèle (à moins que ça ait changé, je sais qu'il y a eu de longues discussions au sein du PHPgroup).

Une solution relativement simple est "tricher" en divisant ton script PHP en 2 et de les lancer deux fois via du HTML.
Démo:
http://www.bellinux.com/fr/italian/4-In ... zzato.html
Quand tout le reste a échoué, lisez le mode d'emploi...

Eléphanteau du PHP | 23 Messages

26 févr. 2009, 19:43

En fait il faut croire que c'est possible : http://matthieu.developpez.com/executio ... ue/#L6.3.4 notamment avec la fonction fopen ()

ViPHP
ViPHP | 1380 Messages

26 févr. 2009, 22:49

Lancer un script PHP en arrière-plan est possible mais avec quelques contorsions. On ouvre un socket, on balance une requête HTTP en prenant soin d'y ajouter une instruction close avant de refermer le socket. Voici la fonction que j'utilise:
/*	Lance un script PHP en background */

function background($url){
	$parts = parse_url($url);
	$socket = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 30);

	if (!$socket) {
		echo $errno, $errstr;
		return false;
	} else {
		$out = "POST ".$parts['path']." HTTP/1.1\r\n";
		$out.= "Host: ".$parts['host']."\r\n";
		$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
		$out.= "Content-Length: ".strlen($parts['query'])."\r\n";
		$out.= "Connection: Close\r\n\r\n";
		if (isset($parts['query'])) $out.= $parts['query'];
		 
		fwrite($socket, $out);
		fclose($socket);
	}
}
ripat

Eléphanteau du PHP | 23 Messages

26 févr. 2009, 22:54

heuuu, ça veut dire que ça va pas marcher ce que je prévoyais ? pourquoi ?
<?php
fopen (script1.php) ;
fopen (script2.php) ;
fopen (script3.php) ;
fopen (script4.php) ;
?>

Mammouth du PHP | 693 Messages

26 févr. 2009, 23:02

avec fopen(), on ouvre le fichier, pour pouvoir ensuite lire son contenu avec d'autres fonctions comme readfile() par exemple. Ce que tu aimerai, c'est demander au serveur d'executer le script que tu donne, donc ca va pas etre possible.

L'autre utilisation de fopen() est quand tu lui donne une adresse. Dans ce cas, tu vas obtenir le résultat de la page donc elle va être interprété. Cependant, on peut pas parler de tread parallèles puisque PHP fonctionnent de manière synchrone, c'est à dire que le script père est en pause le temps que le script fils s'execute.

Eléphanteau du PHP | 23 Messages

26 févr. 2009, 23:09

Merci pour l'explication orgerix :D

Bon, mais finalement, même si j'ai pas très bien saisi son fonctionnement, je dois pouvoir m'en sortir aussi facilement maintenant que je dispose de la fonction proposée par Ripat : (un grand merci :D )
<?php
background($script1);
background($script2);
background($script3);
background($script4);

ViPHP
ViPHP | 1380 Messages

27 févr. 2009, 09:23

Merci pour l'explication orgerix :D

Bon, mais finalement, même si j'ai pas très bien saisi son fonctionnement, je dois pouvoir m'en sortir aussi facilement maintenant que je dispose de la fonction proposée par Ripat
Le script père ouvre autant de sockets que de scripts à lancer. Ces sockets ne servent qu'à envoyer des requêtes http qui appellent les scripts fils. Une fois la requête http lancée et clôturée (instruction close) , on ferme le socket et on passe au suivant. Simple, mais comme la requête et le socket sont fermés immédiatement, il est impossible de gérer le timeout du flux. Il faut donc bien veiller à ce que le script derrière s'exécute sans planter.

Il sera peut-être nécessaire de mettre dans les scripts fils l'instruction
 ignore_user_abort(true); 
Il me semble que ça fonctionne sans mais ça ne mange pas de pain de le mettre.
ripat

Eléphanteau du PHP | 23 Messages

27 févr. 2009, 11:02

Super malin :D

Merci encore, avec l'explication c'est encore mieux :D :D

Eléphanteau du PHP | 23 Messages

01 mars 2009, 12:52

Ha, par contre la mise en pratique à l'air problématique :

Code : Tout sélectionner

Warning: fsockopen() [function.fsockopen]: php_network_getaddresses: getaddrinfo failed: Name or service not known in /home/padawan/public_html/survie_backup/functions.php on line 138 Warning: fsockopen() [function.fsockopen]: unable to connect to :80 (Unknown error) in /home/padawan/public_html/survie_backup/functions.php on line 138 135567036
Le code en question est le même que celui de Ripat, et la ligne 138 est celle-ci :
    $socket = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 30);
Dans la fonction :
function background($url){
    $parts = parse_url($url);
    $socket = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 30);

    if (!$socket) {
        echo $errno, $errstr;
        return false;
    } else {
        $out = "POST ".$parts['path']." HTTP/1.1\r\n";
        $out.= "Host: ".$parts['host']."\r\n";
        $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
        $out.= "Content-Length: ".strlen($parts['query'])."\r\n";
        $out.= "Connection: Close\r\n\r\n";
        if (isset($parts['query'])) $out.= $parts['query'];
         
        fwrite($socket, $out);
        fclose($socket);
    }
}