如何在PHP中实现事件监听 [英] How to implement event listening in PHP

查看:217
本文介绍了如何在PHP中实现事件监听的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是我的问题:我有一个脚本(让我们称之为comet.php)由AJAX客户端脚本要求,并等待发生如下变化:

  while(no_changes){
usleep(100000);
//检查更改
}

很多,它不是很可扩展,它是(imho)坏实践
我想用信号量(?)或任何方式改进这种行为并发编程
技术。你能给我一些提示如何处理这个? (我知道,这不是一个简短的答案,但起点是足够了。)



编辑:关于LibEvent

解决方案

您可以使用 ZeroMQ 解决此问题。



ZeroMQ是一个库提供了用于将事物(线程,进程甚至单独的机器)插入在一起的超级插座。



我假设您正在尝试将数据从服务器推送到客户端。那么,一个很好的方法是使用 EventSource API polyfills可用)。



client.js



通过EventSource连接到stream.php。

  var stream = new EventSource('stream.php'); 

stream.addEventListener('debug',function(event){
var data = JSON.parse(event.data);
console.log([event.type, data]);
});

stream.addEventListener('message',function(event){
var data = JSON.parse(event.data);
console.log([event.type, data]);
});

router.php



这是一个长时间运行的进程,监听收到的消息,并将其发送给任何正在侦听的消息。

  ?php 

$ context = new ZMQContext();

$ pull = $ context-> getSocket(ZMQ :: SOCKET_PULL);
$ pull-> bind(tcp:// *:5555);

$ pub = $ context-> getSocket(ZMQ :: SOCKET_PUB);
$ pub-> bind(tcp:// *:5556);

while(true){
$ msg = $ pull-> recv();
echopublishing received message $ msg \\\
;
$ pub-> send($ msg);
}

stream.php
$ b

每个连接到网站的用户都会获得自己的stream.php。此脚本长时间运行,并等待来自路由器的任何消息。一旦收到新邮件,它将以EventSource格式输出此邮件。

 <?php 

$ context = new ZMQContext();

$ sock = $ context-> getSocket(ZMQ :: SOCKET_SUB);
$ sock-> setSockOpt(ZMQ :: SOCKOPT_SUBSCRIBE,);
$ sock-> connect(tcp://127.0.0.1:5556);

set_time_limit(0);
ini_set('memory_limit','512M');

header(Content-Type:text / event-stream);
header(Cache-Control:no-cache);

while(true){
$ msg = $ sock-> recv();
$ event = json_decode($ msg,true);
if(isset($ event ['type'])){
echoevent:{$ event ['type']} \\\

}
$ data = json_encode($ event ['data']);
echodata:$ data\\\
\\\
;
ob_flush();
flush();
}

要向所有用户发送邮件,只需将其发送到路由器。路由器然后将该消息分发到所有监听流。这里有一个例子:

 <?php 

$ context = new ZMQContext

$ sock = $ context-> getSocket(ZMQ :: SOCKET_PUSH);
$ sock-> connect(tcp://127.0.0.1:5555);

$ msg = json_encode(array('type'=>'debug','data'=> array('foo','bar','baz')));
$ sock-> send($ msg);

$ msg = json_encode(array('data'=> array('foo','bar','baz')));
$ sock-> send($ msg);

这应该证明你不需要node.js做实时编程。 PHP可以处理它很好。



除此之外,socket.io是一个非常好的方法这样做。



另请参阅




here is my problem: I have a script (let's call it comet.php) whic is requsted by an AJAX client script and wait for a change to happen like this:

while(no_changes){
    usleep(100000);
    //check for changes
}

I don't like this too much, it's not very scalable and it's (imho) "bad practice" I would like to improve this behaviour with a semaphore(?) or anyway concurrent programming technique. Can you please give me some tips on how to handle this? (I know, it's not a short answer, but a starting point would be enough.)

Edit: what about LibEvent?

解决方案

You can solve this problem using ZeroMQ.

ZeroMQ is a library that provides supercharged sockets for plugging things (threads, processes and even separate machines) together.

I assume you're trying to push data from the server to the client. Well, a good way to do that is using the EventSource API (polyfills available).

client.js

Connects to stream.php through EventSource.

var stream = new EventSource('stream.php');

stream.addEventListener('debug', function (event) {
    var data = JSON.parse(event.data);
    console.log([event.type, data]);
});

stream.addEventListener('message', function (event) {
    var data = JSON.parse(event.data);
    console.log([event.type, data]);
});

router.php

This is a long-running process that listens for incoming messages and sends them out to anyone listening.

<?php

$context = new ZMQContext();

$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind("tcp://*:5555");

$pub = $context->getSocket(ZMQ::SOCKET_PUB);
$pub->bind("tcp://*:5556");

while (true) {
    $msg = $pull->recv();
    echo "publishing received message $msg\n";
    $pub->send($msg);
}

stream.php

Every user connecting to the site gets his own stream.php. This script is long-running and waits for any messages from the router. Once it gets a new message, it will output this message in EventSource format.

<?php

$context = new ZMQContext();

$sock = $context->getSocket(ZMQ::SOCKET_SUB);
$sock->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, "");
$sock->connect("tcp://127.0.0.1:5556");

set_time_limit(0);
ini_set('memory_limit', '512M');

header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");

while (true) {
    $msg = $sock->recv();
    $event = json_decode($msg, true);
    if (isset($event['type'])) {
        echo "event: {$event['type']}\n";
    }
    $data = json_encode($event['data']);
    echo "data: $data\n\n";
    ob_flush();
    flush();
}

To send messages to all users, just send them to the router. The router will then distribute that message to all listening streams. Here's an example:

<?php

$context = new ZMQContext();

$sock = $context->getSocket(ZMQ::SOCKET_PUSH);
$sock->connect("tcp://127.0.0.1:5555");

$msg = json_encode(array('type' => 'debug', 'data' => array('foo', 'bar', 'baz')));
$sock->send($msg);

$msg = json_encode(array('data' => array('foo', 'bar', 'baz')));
$sock->send($msg);

This should prove that you do not need node.js to do realtime programming. PHP can handle it just fine.

Apart from that, socket.io is a really nice way of doing this. And you could connect to socket.io to your PHP code via ZeroMQ easily.

See also

这篇关于如何在PHP中实现事件监听的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆