I want to implement a simple Server-Sent events app where clients listen to a php file like this
<script src="eventsource.js"></script>
<script>
var es = new EventSource('../sse.php');
es.onmessage = function (event) {
var data = JSON.parse(event.data);
console.log('msg: ' + event.data);
};
es.onopen = function () {
console.log('connected');
}
</script>
but then i need to be able to broadcast a message and every connected client gets it simultaneously.
The php file will be triggered by another request and it will "echo" some SSE data to all clients.
Is this possible? Is there another route i can take?
Thank you in advance
PHP is not going to be great for this. If you have lots of clients waiting for this event, you're going to require an instance of the PHP interpreter (and probably an apache thread) for each client that's waiting.
What you might consider doing is having an event driven server handle this. Node.JS and Tornado (Python) are two environments I've used in the past in similar circumstances. If you use Node.js, you may want to look into socket.io for this -- it doesn't use Server Sent Events, but would make what you want very simple.
You could have two webservers side by side, your current server (I'm assuming Apache) and one written by you to handle the clients waiting for updates. Whenever the PHP server wants to send a message to waiting clients, the PHP server notifies the other server (AMQP, ZeroMQ, redis Pub/Sub or a simple HTTP request on a non-public interface would all be good choices), and that server passes on the message to any waiting clients.
You can see a very simple version of what I'm talking about using node.js + socket.io (Which could easily be replaced by SSE) on github.
important EDIT: (after a day)
after testing i found this is so bad solution.
test case:
result:
6 SSE-connections opened. but 2 SSE-connections left pending. other pages in server cannot be open until close SSE-clients.
but server can handle many clients by ajax (repeat ajax every 1 second).
Old Answer:
use share memory.
sse.php
<?php
header("Content-Type: text/event-stream\n\n");
header('Cache-Control: no-cache');
$key = "987654";
$permissions = 0666;
$size = 1024;
//Create or open the shared memory segment.
$segment = shm_attach($key, $size, $permissions);
$msg = ' null ';
$last_time = 0;
$time = 0;
while (1) {
if (shm_has_var($segment, 0)) {
$time = shm_get_var($segment, 0);
}
if (shm_has_var($segment, 0)) {
$msg = shm_get_var($segment, 1);
}
$now = time();
if ($last_time < $time) {
$last_time = $time;
echo 'data: msg(' . $msg . ') time(' . $time . ')';
echo "\n\n";
}
ob_flush();
flush();
sleep(1);
}
trigger.php
<?php
if (isset($_GET['msg'])) {
$key = "987654";// TODO: how to generate suitable key?
$permissions = 0666;
$size = 1024;
$segment = shm_attach($key, $size, $permissions);
$time = time();
$msg = $_GET['msg'];
shm_put_var($segment, 0, $time);
shm_put_var($segment, 1, $msg);
echo $time;
}
disadvantage of this way:
in my implementation sse.php send only last message in a second. but you can improve it and use database. (if trigger.php called 3 times in a second, then only last message saved)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With