Exemple #1 Exemple de minuteurs
<?php
// Crée et démarre un minuteur qui se lance aprÚs 2 secondes
$w1 = new EvTimer(2, 0, function () {
echo "2 secondes sont passées\n";
});
// Crée et lance un minuteur qui se lance aprÚs 2 secondes, et se répÚte toutes les secondes
// tant qu'on ne le stoppe pas manuellement
$w2 = new EvTimer(2, 1, function ($w) {
echo "est appelé chaque seconde, et est lancé aprÚs 2 secondes\n";
echo "itération = ", Ev::iteration(), PHP_EOL;
// Stoppe le watcher aprÚs 5 itérations
Ev::iteration() == 5 and $w->stop();
// Stoppe le watcher si les prochains appels provoquent plus de 10 itérations
Ev::iteration() >= 10 and $w->stop();
});
// CrĂ©e un minuteur stoppĂ©. Il restera inactif tant que nous ne le dĂ©marrons pas nous mĂȘme
$w_stopped = EvTimer::createStopped(10, 5, function($w) {
echo "Fonction de rappel d'un minuteur créé arrĂȘtĂ©\n";
// Stoppe le watcher aprÚs 2 itérations
Ev::iteration() >= 2 and $w->stop();
});
// Boucle tant que Ev::stop() n'est pas appelé ou que tous les watchers ne soient stoppés
Ev::run();
// Démarre et regarde si ça fonctionne
$w_stopped->start();
echo "Exécute une seule itération\n";
Ev::run(Ev::RUN_ONCE);
echo "RedĂ©marre le second watcher et tente de gĂ©rer le mĂȘme Ă©vĂ©nement, mais ne bloque pas\n";
$w2->again();
Ev::run(Ev::RUN_NOWAIT);
$w = new EvTimer(10, 0, function() {});
echo "Exécution d'une boucle bloquante\n";
Ev::run();
echo "END\n";
?>Résultat de l'exemple ci-dessus est similaire à :
2 secondes sont passĂ©es est appelĂ© chaque seconde, et est lancĂ© aprĂšs 2 secondes itĂ©ration = 1 est appelĂ© chaque seconde, et est lancĂ© aprĂšs 2 secondes itĂ©ration = 2 est appelĂ© chaque seconde, et est lancĂ© aprĂšs 2 secondes itĂ©ration = 3 est appelĂ© chaque seconde, et est lancĂ© aprĂšs 2 secondes itĂ©ration = 4 est appelĂ© chaque seconde, et est lancĂ© aprĂšs 2 secondes itĂ©ration = 5 ExĂ©cute une seule itĂ©ration Fonction de rappel d'un minuteur créé arrĂȘtĂ© RedĂ©marre le second watcher et tente de gĂ©rer le mĂȘme Ă©vĂ©nement, mais ne bloque pas ExĂ©cution d'une boucle bloquante est appelĂ© chaque seconde, et est lancĂ© aprĂšs 2 secondes itĂ©ration = 8 est appelĂ© chaque seconde, et est lancĂ© aprĂšs 2 secondes itĂ©ration = 9 est appelĂ© chaque seconde, et est lancĂ© aprĂšs 2 secondes itĂ©ration = 10 END
Exemple #2 Minuteur périodique. Alerte toutes les 10.5 secondes
<?php
$w = new EvPeriodic(0., 10.5, NULL, function ($w, $revents) {
echo time(), PHP_EOL;
});
Ev::run();
?>Exemple #3 Minuteur périodique. Utilisation de la fonction de rappel de reprogrammation
<?php
// Alerte toutes les 10.5 secondes
function reschedule_cb ($watcher, $now) {
return $now + (10.5. - fmod($now, 10.5));
}
$w = new EvPeriodic(0., 0., "reschedule_cb", function ($w, $revents) {
echo time(), PHP_EOL;
});
Ev::run();
?>Exemple #4 Minuteur périodique. Alerte toutes les 10.5 secondes, en commençant maintenant
<?php
// Alerte toutes les 10.5 secondes en commençant maintenant
$w = new EvPeriodic(fmod(Ev::now(), 10.5), 10.5, NULL, function ($w, $revents) {
echo time(), PHP_EOL;
});
Ev::run();
?>Exemple #5 Attend que STDIN devienne accessible en lecture
<?php
// Attend que STDIN devienne accessible en lecture
$w = new EvIo(STDIN, Ev::READ, function ($watcher, $revents) {
echo "STDIN est accessible en lecture\n";
});
Ev::run(Ev::RUN_ONCE);
?>Exemple #6 Utilisation de quelques I/O asynchrones pour accéder à un socket
<?php
/* Utilise quelques I/O asynchrone pour accéder à un socket */
// L'extension `sockets' va continuer d'historiser les alertes
// pour EINPROGRESS, EAGAIN/EWOULDBLOCK etc.
error_reporting(E_ERROR);
$e_nonblocking = array (/*EAGAIN or EWOULDBLOCK*/11, /*EINPROGRESS*/115);
// RécupÚre le port pour le service WWW
$service_port = getservbyname('www', 'tcp');
// RécupÚre l'adresse IP pour l'hÎte cible
$address = gethostbyname('google.co.uk');
// Crée un socket TCP/IP
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === FALSE) {
echo "Ăchec de socket_create() : raison : "
.socket_strerror(socket_last_error()) . "\n";
}
// Définit le drapeau O_NONBLOCK
socket_set_nonblock($socket);
// On stoppe une fois le délai maximal d'attente atteint
$timeout_watcher = new EvTimer(10.0, 0., function () use ($socket) {
socket_close($socket);
Ev::stop(Ev::BREAK_ALL);
});
// Effectue une requĂȘte HEAD lorsque le socket est accessible en Ă©criture
$write_watcher = new EvIo($socket, Ev::WRITE, function ($w)
use ($socket, $timeout_watcher, $e_nonblocking)
{
// Stoppe le watcher timeout
$timeout_watcher->stop();
// Stoppe le watcher write
$w->stop();
$in = "HEAD / HTTP/1.1\r\n";
$in .= "Host: google.co.uk\r\n";
$in .= "Connection: Close\r\n\r\n";
if (!socket_write($socket, $in, strlen($in))) {
trigger_error("Ăchec lors de l'Ă©criture de $in dans le socket", E_USER_ERROR);
}
$read_watcher = new EvIo($socket, Ev::READ, function ($w, $re)
use ($socket, $e_nonblocking)
{
// Le socket est accessible en lecture. recv() a reçu 20 octets en utilisant le mode non bloquant
$ret = socket_recv($socket, $out, 20, MSG_DONTWAIT);
if ($ret) {
echo $out;
} elseif ($ret === 0) {
// Tout a été lu
$w->stop();
socket_close($socket);
return;
}
// On attrape EINPROGRESS, EAGAIN, ou EWOULDBLOCK
if (in_array(socket_last_error(), $e_nonblocking)) {
return;
}
$w->stop();
socket_close($socket);
});
Ev::run();
});
$result = socket_connect($socket, $address, $service_port);
Ev::run();
?>Résultat de l'exemple ci-dessus est similaire à :
HTTP/1.1 301 Moved Permanently Location: http://www.google.co.uk/ Content-Type: text/html; charset=UTF-8 Date: Sun, 23 Dec 2012 16:08:27 GMT Expires: Tue, 22 Jan 2013 16:08:27 GMT Cache-Control: public, max-age=2592000 Server: gws Content-Length: 221 X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN Connection: close
Exemple #7 Encapsule une boucle dans une autre
<?php
/*
* Tente de récupérer une boucle d'événement encapsulable, et l'encapsule dans
* une boucle d'événements par défaut. Si c'est possible, on utilise la boucle
* par défaut. La boucle par défaut est stockée dans $loop_hi, alors que la boucle
* encapsulable est stockĂ©e dans $loop_lo( qui est $loop_hi dans le cas oĂč
* aucune boucle encapsulable ne peut ĂȘtre utilisĂ©e).
*
* Exemple traduit en PHP de :
* http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Examples_CONTENT-9
*/
$loop_hi = EvLoop::defaultLoop();
$loop_lo = NULL;
$embed = NULL;
/*
* Regarde s'il y a une chance d'en récupérer une qui fonctionne
* (une valeur de drapeau à 0 signifie une auto-détection)
*/
$loop_lo = Ev::embeddableBackends() & Ev::recommendedBackends()
? new EvLoop(Ev::embeddableBackends() & Ev::recommendedBackends())
: 0;
if ($loop_lo) {
$embed = new EvEmbed($loop_lo, function () {});
} else {
$loop_lo = $loop_hi;
}
?>Exemple #8 Encapsule une boucle créée avec le backend kqueue dans la boucle par défaut
<?php
/*
* Vérifie si kqueue est disponible mais non recommandé, et crée un backend kqueue
* pour l'utiliser avec les sockets (ce qui fonctionne avec toutes les implémentations kqueue).
* Stocke la boucle d'événements kqueue/uniquement-socket dans loop_socket. (On peut
* également utiliser EVFLAG_NOENV)
*
* Exemple repris depuis :
* http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Examples_CONTENT-9
*/
$loop = EvLoop::defaultLoop();
$socket_loop = NULL;
$embed = NULL;
if (Ev::supportedBackends() & ~Ev::recommendedBackends() & Ev::BACKEND_KQUEUE) {
if (($socket_loop = new EvLoop(Ev::BACKEND_KQUEUE))) {
$embed = new EvEmbed($loop);
}
}
if (!$socket_loop) {
$socket_loop = $loop;
}
// Maintenant, on peut utiliser $socket_loop pour toutes les sockets, et $loop pour tout le reste
?>Exemple #9 Gestion du signal SIGTERM
<?php
$w = new EvSignal(SIGTERM, function ($watcher) {
echo "On reçoit un SIGTERM\n";
$watcher->stop();
});
Ev::run();
?>Exemple #10 Surveillance des modifications dans /var/log/messages
<?php
// Utilisation d'un intervalle de mise Ă jour de 10 secondes.
$w = new EvStat("/var/log/messages", 8, function ($w) {
echo "Modification dans /var/log/messages\n";
$attr = $w->attr();
if ($attr['nlink']) {
printf("Taille courante : %ld\n", $attr['size']);
printf("atime actuel : %ld\n", $attr['atime']);
printf("mtime actuel : %ld\n", $attr['mtime']);
} else {
fprintf(STDERR, "Le fichier `messages` n'est plus ici !");
$w->stop();
}
});
Ev::run();
?>Exemple #11 Surveillance des modifications dans /var/log/messages. On regarde les modifications avec une seconde de délai
<?php
$timer = EvTimer::createStopped(0., 1.02, function ($w) {
$w->stop();
$stat = $w->data;
// 1 seconde aprĂšs la derniĂšre modification d'un fichier
printf("Taille actuelle : %ld\n", $stat->attr()['size']);
});
$stat = new EvStat("/var/log/messages", 0., function () use ($timer) {
// Réinitialise le watcher timer
$timer->again();
});
$timer->data = $stat;
Ev::run();
?>Exemple #12 Modification du statut d'un processus
<?php
$pid = pcntl_fork();
if ($pid == -1) {
fprintf(STDERR, "pcntl_fork a échoué\n");
} elseif ($pid) {
$w = new EvChild($pid, FALSE, function ($w, $revents) {
$w->stop();
printf("Le processus %d est sorti avec un statut %d\n", $w->rpid, $w->rstatus);
});
Ev::run();
// Protection contre les Zombies
pcntl_wait($status);
} else {
// On fork le fils
exit(2);
}
?>