我遇到一些困难,让PHP libevent扩展在超时时突破循环。这是我到目前为止基于PHP.net文档页面上的演示:
// From here: http://www.php.net/manual/en/libevent.examples.php
function print_line($fd, $events, $arg) {
static $max_requests = 0;
$max_requests++;
printf("Received event: %s after %s\n%s", implode(getEventFlags($events)), getTimer(), fgets($fd));
if ($max_requests == 10) {
// exit loop after 3 writes
echo " [EXIT]\n";
event_base_loopexit($arg[1]);
}
}
// create base and event
$base = event_base_new();
$event = event_new();
getTimer(); // Initialise time
$fd = STDIN;
event_set($event, $fd, EV_READ | EV_PERSIST, "print_line", array($event, $base));
event_base_set($event, $base);
event_add($event, 2000000);
event_base_loop($base);
// extract flags from bitmask
function getEventFlags ($ebm) {
$expFlags = array('EV_TIMEOUT', 'EV_SIGNAL', 'EV_READ', 'EV_WRITE', 'EV_PERSIST');
$ret = array();
foreach ($expFlags as $exf) {
if ($ebm & constant($exf)) {
$ret[] = $exf;
}
}
return $ret;
}
// Used to track time!
function getTimer () {
static $ts;
if (is_null($ts)) {
$ts = microtime(true);
return "Timer initialised";
}
$newts = microtime(true);
$r = sprintf("Delta: %.3f", $newts - $ts);
$ts = $newts;
return $r;
}
我可以看到传递给event_add
的超时值会影响传递给print_line()的事件,如果这些事件间隔超过2秒,我会得到EV_TIMEOUT
而不是{{1} }}。然而,我想要的是让libevent在达到超时时立即调用EV_READ
,而不是等待下一个事件以便给我超时。
我尝试过使用print_line
,这会导致事件循环立即退出而不会阻塞事件。我也尝试将event_base_loopexit($base, 2000000)
传递给EV_TIMEOUT
,这似乎根本没有效果。
以前有人设法让这个工作吗?我知道event_buffer_ *的东西适用于超时,但我想使用标准的event_set
函数。关于event_timer_ *函数的PECL bugs讨论之一和我的系统上确实存在这些函数,但它们根本没有记录。
答案 0 :(得分:0)
问题出在fgets()中:
printf("Received event: %s after %s\n%s", implode(getEventFlags($events)), getTimer(), fgets($fd));
这会阻止处理并等待来自STDIN的数据(但超时时没有)
改为:
$text = '';
if ($events & EV_READ) {
$text = fgets($fd);
}
printf("Received event: %s after %s\n%s", implode(getEventFlags($events)), getTimer(), $text);