php的libev扩展
提供了一些类似nodejs异步调用的方式,
用途很多,如文件状态监视,流阻塞等待异步
pecl库的,默认不安装,需要自己在pecl下弄个过来
php manual地址:http://www.php.net/manual/zh/ev.examples.php
如果不知道libev是啥可以看这个http://dirlt.com/libev.html
这里罗列下具体手册内的代码,只翻译了关键注释
刚才由于对代码没有整理,竟然被过滤掉了……不能发html pre代码的博客编辑器好凄惨
// 创建一个定时器,2秒后启动,不循环只执行一次
$w1 = new EvTimer(2, 0, function () {
echo "2 seconds elapsed\n";
});
// 创建一个定时器,2秒后启动,1秒执行一次
// 直到碰到指定代码停止
$w2 = new EvTimer(2, 1, function ($w) {
echo "is called every second, is launched after 2 seconds\n";
echo "iteration = ", Ev::iteration(), PHP_EOL;
// 执行第五次停止
Ev::iteration() == 5 and $w->stop();
// Stop the watcher if further calls cause more than 10 iterations
Ev::iteration() >= 10 and $w->stop();
});
//创建计时器,未激活,需要代码激活
$w_stopped = EvTimer::createStopped(10, 5, function($w) {
echo "Callback of a timer created as stopped\n";
// 事件产生两次后停止定时器
Ev::iteration() >= 2 and $w->stop();
});
// 循环直到所有都关闭
Ev::run();
// 启动并检查是否开始工作
$w_stopped->start();
echo "Run single iteration\n";
Ev::run(Ev::RUN_ONCE);
echo "重启定时器,并尝试继续处理相同事件,但是这次是非阻塞的方式\n";
$w2->again();
Ev::run(Ev::RUN_NOWAIT);
$w = new EvTimer(10, 0, function() {});
echo "阻塞方式运行\n";
Ev::run();
echo "END\n";
========================
// 等待一直到STDIN准备好并可读
$w = new EvIo(STDIN, Ev::READ, function ($watcher, $revents) {
echo "STDIN is readable\n";
});
Ev::run(Ev::RUN_ONCE);
========================
非阻塞
$e_nonblocking = array (11, 115);
// 获取www服务服务端口
$service_port = getservbyname('www', 'tcp');
// 获取域名对应ip
$address = gethostbyname('google.co.uk');
//创建socket通讯
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === FALSE) {
echo "socket_create() failed: reason: "
.socket_strerror(socket_last_error()) . "\n";
}
// 表示非阻塞方式
socket_set_nonblock($socket);
// 如果在使用中超时自动关闭,这里用了evtimer
$timeout_watcher = new EvTimer(10.0, 0., function () use ($socket) {
socket_close($socket);
Ev::stop(Ev::BREAK_ALL);
});
// 当socket可用后,进行发送接收操作
$write_watcher = new EvIo($socket, Ev::WRITE, function ($w)
use ($socket, $timeout_watcher, $e_nonblocking)
{
// 超时timer停用
$timeout_watcher->stop();
// 停用evio监视
$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("Failed writing $in to socket", E_USER_ERROR);
}
$read_watcher = new EvIo($socket, Ev::READ, function ($w, $re)
use ($socket, $e_nonblocking)
{
// 非阻塞情况下从socket读取20字节数据
$ret = socket_recv($socket, $out, 20, MSG_DONTWAIT);
if ($ret) {
echo $out;
} elseif ($ret === 0) {
// 读取完毕
$w->stop();
socket_close($socket);
return;
}
// socket通讯错误
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();
===========================
信号处理,当收到控制信号时自动启动
$w = new EvSignal(SIGTERM, function ($watcher) {
echo "SIGTERM received\n";
$watcher->stop();
});
Ev::run();
===========================
// 指定文件修改监视当监视文件出现变化,则触发,每8秒检查一次
$w = new EvStat("/var/log/messages", 8, function ($w) {
echo "/var/log/messages changed\n";
$attr = $w->attr();
if ($attr['nlink']) {
printf("Current size: %ld\n", $attr['size']);
printf("Current atime: %ld\n", $attr['atime']);
printf("Current mtime: %ld\n", $attr['mtime']);
} else {
fprintf(STDERR, "`messages` file is not there!");
$w->stop();
}
});
Ev::run();
============================
进程状态监视
$pid = pcntl_fork();
if ($pid == -1) {
fprintf(STDERR, "pcntl_fork failed\n");
} elseif ($pid) {
$w = new EvChild($pid, FALSE, function ($w, $revents) {
$w->stop();
printf("Process %d exited with status %d\n", $w->rpid, $w->rstatus);
});
Ev::run();
// Protect against Zombies
pcntl_wait($status);
} else {
//Forked child
exit(2);
}