Read long-运行 PHP 进程客户端
Read long-running PHP process client side
我想读取一个长 运行 php 进程,该进程将在满足条件时 return 数据。
根据我的研究,我发现:
- 长轮询
- 套接字 (socket.io & node.js)
- 棘轮
我正在努力理解和应用我的问题的实现。我在 PHP 中有以下循环:
public function store(ClientImpl $a)
{
$request = \Illuminate\Support\Facades\Request::all();
$originateMsg = new OriginateAction('Local/' . $request['agent'] . '@auto-answer');
$originateMsg->setContext('G-Outgoing');
$originateMsg->setPriority('1');
$originateMsg->setExtension($request['dial']);
$a->send($originateMsg);
while(true) {
if( $a->process() ) break;
usleep(1000);
}
$a->close();
echo 'OK';
ob_end_flush();
flush();
}
$a->process()
调用以下方法:
/**
* Main processing loop. Also called from send(), you should call this in
* your own application in order to continue reading events and responses
* from ami.
*/
public function process()
{
$msgs = $this->getMessages();
foreach ($msgs as $aMsg) {
if ($this->_logger->isDebugEnabled()) {
$this->_logger->debug(
'------ Received: ------ ' . "\n" . $aMsg . "\n\n"
);
}
$resPos = strpos($aMsg, 'Response:');
$evePos = strpos($aMsg, 'Event:');
if (($resPos !== false) && (($resPos < $evePos) || $evePos === false)) {
$response = $this->_messageToResponse($aMsg);
$this->_incomingQueue[$response->getActionId()] = $response;
} else if ($evePos !== false) {
$event = $this->_messageToEvent($aMsg);
$response = $this->findResponse($event);
if ($response === false || $response->isComplete()) {
$this->dispatch($event);
} else {
$response->addEvent($event);
}
} else {
// broken ami.. sending a response with events without
// Event and ActionId
$bMsg = 'Event: ResponseEvent' . "\r\n";
$bMsg .= 'ActionId: ' . $this->_lastActionId . "\r\n" . $aMsg;
$event = $this->_messageToEvent($bMsg);
$response = $this->findResponse($event);
$response->addEvent($event);
}
if ($this->_logger->isDebugEnabled()) {
$this->_logger->debug('----------------');
}
}
}
$a->process()
然后堆叠事件消息,为了读取这些我创建了 IEventListener
的实现,当 $a->process()
被调用时它也被称为 'behind the scenes'。
class VoipEventStart implements IEventListener
{
public function handle(EventMessage $event)
{
$a = $event->getKeys();
if( ($a['event'] == "Hangup" || $a['event'] == "HangupRequest") && strpos($a['channel'], 'SIP/') !== FALSE)
{
return true;
}
return false;
}
}
process 方法在用户进行活动呼叫时从 Asterisk PBX 系统读取事件。这意味着只要调用持续,流程循环就会持续。
如果浏览器看起来不像 loading/waiting,我将如何执行此客户端?
您可以使用 Server Sent Events 或某些套接字实现,但最简单的方法可能是长轮询策略就足够了。
为此,从客户端发送一个普通的 AJAX 请求,并在满足条件时使服务器仅 return。它可以像更改服务器端代码一样简单,如下所示:
while(true) {
if( $a->process() ) break;
usleep(1000);
}
echo 'OK';
ob_end_flush();
flush();
并且客户端应向启动上述循环的 PHP 文件发送一个简单的 GET 请求。这样当响应返回到这个请求时,你知道 process() return true.
客户端代码可能如下所示:
<div>Call status: <span id="status">In call</span></div>
<script>
$.get('/check_call_status.php?callerId=123', function(response) {
if(response === 'OK') {
$('#staus').html('finished');
}
});
</script>
当然,这可以更复杂地处理超时。例如。如果在给定时间段内没有对长轮询请求的响应,请重新启动它 - 即中止请求并再次发送它以避免客户端或服务器超时。
我想读取一个长 运行 php 进程,该进程将在满足条件时 return 数据。
根据我的研究,我发现:
- 长轮询
- 套接字 (socket.io & node.js)
- 棘轮
我正在努力理解和应用我的问题的实现。我在 PHP 中有以下循环:
public function store(ClientImpl $a)
{
$request = \Illuminate\Support\Facades\Request::all();
$originateMsg = new OriginateAction('Local/' . $request['agent'] . '@auto-answer');
$originateMsg->setContext('G-Outgoing');
$originateMsg->setPriority('1');
$originateMsg->setExtension($request['dial']);
$a->send($originateMsg);
while(true) {
if( $a->process() ) break;
usleep(1000);
}
$a->close();
echo 'OK';
ob_end_flush();
flush();
}
$a->process()
调用以下方法:
/**
* Main processing loop. Also called from send(), you should call this in
* your own application in order to continue reading events and responses
* from ami.
*/
public function process()
{
$msgs = $this->getMessages();
foreach ($msgs as $aMsg) {
if ($this->_logger->isDebugEnabled()) {
$this->_logger->debug(
'------ Received: ------ ' . "\n" . $aMsg . "\n\n"
);
}
$resPos = strpos($aMsg, 'Response:');
$evePos = strpos($aMsg, 'Event:');
if (($resPos !== false) && (($resPos < $evePos) || $evePos === false)) {
$response = $this->_messageToResponse($aMsg);
$this->_incomingQueue[$response->getActionId()] = $response;
} else if ($evePos !== false) {
$event = $this->_messageToEvent($aMsg);
$response = $this->findResponse($event);
if ($response === false || $response->isComplete()) {
$this->dispatch($event);
} else {
$response->addEvent($event);
}
} else {
// broken ami.. sending a response with events without
// Event and ActionId
$bMsg = 'Event: ResponseEvent' . "\r\n";
$bMsg .= 'ActionId: ' . $this->_lastActionId . "\r\n" . $aMsg;
$event = $this->_messageToEvent($bMsg);
$response = $this->findResponse($event);
$response->addEvent($event);
}
if ($this->_logger->isDebugEnabled()) {
$this->_logger->debug('----------------');
}
}
}
$a->process()
然后堆叠事件消息,为了读取这些我创建了 IEventListener
的实现,当 $a->process()
被调用时它也被称为 'behind the scenes'。
class VoipEventStart implements IEventListener
{
public function handle(EventMessage $event)
{
$a = $event->getKeys();
if( ($a['event'] == "Hangup" || $a['event'] == "HangupRequest") && strpos($a['channel'], 'SIP/') !== FALSE)
{
return true;
}
return false;
}
}
process 方法在用户进行活动呼叫时从 Asterisk PBX 系统读取事件。这意味着只要调用持续,流程循环就会持续。
如果浏览器看起来不像 loading/waiting,我将如何执行此客户端?
您可以使用 Server Sent Events 或某些套接字实现,但最简单的方法可能是长轮询策略就足够了。
为此,从客户端发送一个普通的 AJAX 请求,并在满足条件时使服务器仅 return。它可以像更改服务器端代码一样简单,如下所示:
while(true) {
if( $a->process() ) break;
usleep(1000);
}
echo 'OK';
ob_end_flush();
flush();
并且客户端应向启动上述循环的 PHP 文件发送一个简单的 GET 请求。这样当响应返回到这个请求时,你知道 process() return true.
客户端代码可能如下所示:
<div>Call status: <span id="status">In call</span></div>
<script>
$.get('/check_call_status.php?callerId=123', function(response) {
if(response === 'OK') {
$('#staus').html('finished');
}
});
</script>
当然,这可以更复杂地处理超时。例如。如果在给定时间段内没有对长轮询请求的响应,请重新启动它 - 即中止请求并再次发送它以避免客户端或服务器超时。