server-sent event in php

https://lucidar.me/en/web-dev/server-sent-event-simple-php-example/

关于php如何触发EventSource SSE事件? https://www.codenong.com/9565290/

Server-sent events and php – what triggers events on the server? https://stackoverflow.com/questions/14564903/server-sent-events-and-php-what-triggers-events-on-the-server

Using server-sent events https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

HTML SSE API https://www.w3schools.com/html/html5_serversentevents.asp

****注意事项
如果是nginx需要执行下面操作才起作用
方法1
header(‘X-Accel-Buffering: no’); 在文件头加,方便灵活

方法2
fastcgi_buffering off;  要修改nginx的整体配置文件在http区 这咱方法不灵活

# Introduction

Web servers are built to send data to the client. Sometime, the browser needs to update its content with the information sent by the server without reloading the page. For example, in a chat, when a new message is received, the message is displayed in the client without reloading the page. Another example is when the server performs a long task and a progress bar is displayed in the client browser. The server has send its current status (its progress) to the client.

A common option is to use pooling, most of the time, based on Ajax request. In pooling, the client regularly asks the current state of the server, for example every second. The drawback of this solution is that it overloads the network and the server. It becomes a problem when the number of clients increases.

A great option is to use server-sent event (SSE). SSE is a mecanism in which the server sends events to the client. Actually, an event consists of two things :

  • the event (something happens)
  • the data (contains informations sent to the client)

The third option is to use Websockets. Websockets are suitable for bidirectional communication between the client and the server. Therefore, it’s a bit tricky to implement Websockets in PHP. The combination of SSE and Ajax is a great alternative.

# How it works

SSE communication is always initiated by the client. This is the first step in the following diagram. The client send a request to the server to open the stream:

Server-sent event overview of the communicaiton between the server and the client

Once the stream is open, the server can send as many events as necessary to the client. This is illustrated by steps 2 to 7 in the above diagram. When the communication is over, the server closes the stream.

# PHP simple example

To understand how SSE works, I try to write the simplest example possible. In this example, the client script is composed of an HTML title, an empty list (<ol>) and a JavaScript code The JS script opens a stream with the server. Every 2 seconds, the server send an event containing the current time. The message received by the client is appended to the HTML list.

 

# Client side

On client side, the core the the HTML is composed of an empty list:

<ol id="list">
</ol>

The JavaScript opens the stream with the server, here the script sse.php:

// Create new event, the server script is sse.php
var eventSource = new EventSource("sse.php");

Every time the server send an event, the onmessage event is triggered and the data (event.data) is appended to the list:

// Event when receiving a message from the server
eventSource.onmessage = function(event) {
    // Append the message to the ordered list
    document.getElementById("list").innerHTML += '<li>'+event.data + "</li>";
};

# Server side

On server side, the PHP script first create an event stream. The no-cache option prevent browser from caching the stream.

<?php
// Set file mime type event-stream
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

On this simple example, the core of the script is based on an infinite loop:

// Loop until the client close the stream
while (true) {

To send an event, just echo a string starting with “"data:"“”. Here, we send the current date time. Since PHP buffered output before sending to the client, we’ll need to flush the buffer to send the event:

// Echo time
$time = date('r');
echo "data: The server time is: {$time}\n\n";

// Flush buffer (force sending data to client)
flush();

Note that in the present example, the stream is never closed since we wrote an inifinte loop. The stream ends when the client closes the tab in its browser. Sometime PHP scripts continue running even if the tab is closed. The following line prevents this problem:

if(connection_aborted()) exit();

Note that according to the PHP configuration, the server may buffered data before sending it to the client. You have to check that parameters output_buffering et zlib.output_compression
are disabled in file php.ini:

output_buffering = Off
zlib.output_compression = Off

# Source code

The following code is the client script index.html.

<h1>SSE demo with PHP</h1>

<ol id="list">
</ol>

<script>
  // Create new event, the server script is sse.php
  var eventSource = new EventSource("sse.php");

  // Event when receiving a message from the server
  eventSource.onmessage = function(event) {
    // Append the message to the ordered list
    document.getElementById("list").innerHTML += '<li>'+event.data + "</li>";
  };
</script>

The following PHP script is the event stream sse.php:

<?php
// Set file mime type event-stream
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

// Loop until the client close the stream
while (true) {

  // Echo time
  $time = date('r');
  echo "data: The server time is: {$time}\n\n";

  // Flush buffer (force sending data to client)
  flush();

  // Wait 2 seconds for the next message / event
  sleep(2);  
}
?>

发表评论

电子邮件地址不会被公开。 必填项已用*标注