Page 1 sur 1

Comment utiliser sleep () plusieurs fois simultanément dans

Posté : 26 févr. 2009, 04:49
par new morning
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
}

Posté : 26 févr. 2009, 09:42
par @rthur
Bonjour,

Oui c'est possible.
(A part le "simultanément" qui n'est pas possible)

Posté : 26 févr. 2009, 10:21
par new morning
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:

Posté : 26 févr. 2009, 10:50
par @rthur
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

Posté : 26 févr. 2009, 19:43
par new morning
En fait il faut croire que c'est possible : http://matthieu.developpez.com/executio ... ue/#L6.3.4 notamment avec la fonction fopen ()

Posté : 26 févr. 2009, 22:49
par Ripat
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);
	}
}

Posté : 26 févr. 2009, 22:54
par new morning
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) ;
?>

Posté : 26 févr. 2009, 23:02
par orgerix
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.

Posté : 26 févr. 2009, 23:09
par new morning
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);

Posté : 27 févr. 2009, 09:23
par Ripat
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.

Posté : 27 févr. 2009, 11:02
par new morning
Super malin :D

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

Posté : 01 mars 2009, 12:52
par new morning
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);
    }
}