Just recently, it became known that
Firefox 6 will receive SSE (
already in Opera 10.6+, Chrome, WebKit 5+, iOS Safari 4+, Opera Mobile 10+) so that more than half of all browsers (user reach) are no longer supported. by the mountains. It is time to look at this technology. SSE
proposed Ian Hickson more than 7 years ago, but only a year ago it began to appear in browsers. We have WebSockets, why do we need another protocol? But everything has its pros and cons, let's see what SSE can be useful for.
The idea of SSE is simple - the client subscribes to server events and as soon as an event occurs - the client immediately receives a notification and some data associated with this event. To understand the usefulness of the SSE protocol, it is necessary to compare it with the usual methods of receiving events, briefly explain their essence:
Polling
The simplest, but the most inefficient, method: the client polls the server once every few seconds for events. Even if there is nothing, then the client makes a request vseravno - and you never know what will come.
Pros:- Simply
- Data can be shipped
Minuses:- A lot of extra requests
- Events always come late
- The server has to store events until the client picks them up or until they become obsolete
Long polling
An improved version of the previous method. The client sends a request to the server, the server keeps the connection open until some data arrives or the client disconnects on its own. As soon as the data has arrived, the response is sent and the connection is closed and the next is opened and so on.
Pluses in comparison with Polling:- Minimum number of requests
- High temporal accuracy of events
- The server stores events only for the time of reconnect
Cons compared to Polling:- More complicated circuit
')
WebSockets
This is a binary duplex protocol that allows the client and server to communicate on an equal footing. This protocol can be used for games, chats and all those applications where you need extremely accurate events close to real time.
Pluses in comparison with Long Polling:- One connection rises
- Extremely high temporal accuracy of events
- Manage network failures controlled by browser
Cons compared to Long Polling:- HTTP is not a compatible protocol, you need your server, debugging is complicated
So why is it worth using SSE, since we have such a great protocol WebSockets ?! First, not every web application needs two-way communication — SSE will do. Secondly, SSE is an HTTP compliant protocol and you can implement event broadcasting on any web server.
Server-Sent Events Protocol
The client sends a request to the server, the server sends the following header in response:
Content-Type: text/event-stream
And it does not close the connection (on php you can create an infinite loop, how to do it on node.js will be explained in the sample article). That's it - SSE works! To send some data to the client, the server simply writes a string of the following format to the socket:
data: My message\n\n
If you need to send several lines of data, the format will be as follows:
data: {\n data: "msg": "hello world",\n data: "id": 12345\n data: }\n\n
Here, in principle, and the entire base of the protocol. In addition, the server can send an id message, it is necessary in case the connection was terminated. If the connection was dropped, the client will send a special header (Last-Event-ID) when trying to connect to recover lost events:
id: 12345\n data: GOOG\n data: 556\n\n
Retry time in case of errors:
retry: 10000\n data: hello world\n\n
The id and retry fields are optional.
On the client, everything will look like this:
var source = new EventSource('http://localhost/stream.php'); source.addEventListener('message', function(e) {
Everything is very simple. Let's build an application based on the SSE protocol. As usual, it will be a chat.
Multipart XMLHTTPRequest
Also called multipart streaming (Supports only Firefox). Very similar to SSE protocol.
Its title has a format:
Content-type: multipart/x-mixed-replace;boundary=smthing
And the parts are sent in this format:
Content-type: text/html\r\n\r\n --smthing\n Message\n --smthing\n
The client creates a regular XHR, but before sending the request, you must set the flag
req.multipart = true;
Does it look like SSE?
Read moreThere is another protocol that can lead to SSE:
XMLHTTPRequest: Interactive
To use it, browser support for the special readyState with code 3 (interactive) is necessary - this status indicates that part of the data has arrived, but the connection has not yet been closed. For jQuery, there is a
plugin of the same name that uses readyState with code 3. And as always, not all browsers support readyState with code 3.
Example: Chat on Server-Sent Events
We will receive a stream of events on SSE: going offline, coming online, posting. Because SSE can not send a message, then we will send them via HTTP.
The scheme of work is as follows:
- At the entrance to the chat name is requested
- The client connects to the chat server. It creates a stream of events.
- When a client connects, the chat sends to all the event:% username% online
- When a client disconnects, the chat sends to all the event:% username% offline
- The client can send a message via HTTP "POST / message" The server accepts this message and sends the received message to all clients via SSE
Let's sort the client code. In order for some browsers not to have an infinite download, instead of $ .ready, we execute setTimeout:
setTimeout(function () {
Requesting username:
Create an EventSource and pass it the user name (now the user is online) and listen to the necessary events:
var eventSrc = new EventSource("/event?name=" + name);
I will not consider the renderMessage method and page layout. All client code can be viewed here:
index.htmlOn the server side we will have Node.js. Everything is more complicated here, but the main difficulty in multicast messages from one user to all, and not in building communication via SSE.
We connect the necessary modules
var http = require('http'), fs = require('fs'), qs = require('querystring'), parse = require('url').parse;
Routs
Create a list of routes Routes, which includes the following objects:
1. Static. Index page, we just helmet statics: 'GET /': function (request, response) {
2. Raising the SSE connection: 'GET /event': function (request, response) { var url = parse(request.url, true); var name = (url.query.name || 'anonymous').substr(0, 20); var clientId = Clients.generateClientId();
3. Message from customer: 'POST /message': function (request, response) { var data = '';
4. Route by default - Page 404: $: function (request, response) { response.writeHead(404); response.end(); }
Client Manager - Clients
When adding a new client (add), the manager sends the entire message that the client has arrived:
add: function (clientId, response, name) { this._clients[clientId] = {response: response, name: name || 'anonymous'}; this.count++;
When deleting closes the connection and sends to all that the client is offline:
remove: function (clientId) {
To send messages to clients, use the private _send method:
_send: function (clients, message, name, isbot) { if (!message || !name) { return; }
The _send method uses public broadcast and unicast methods to send messages to all and one client, respectively.
Create and enable the server
Source server.jsOur SSE chat is ready. We start the server:
$ node server.js
Open one of the browsers: Firefox 6, Opera 10.6+, Chrome, WebKit 5+, iOS Safari 4+, Opera Mobile 10+. Go to
http://
localhost/
and chat!
Conclusion
SSE is a good technology that should replace Long Poling; it is simple and no less effective than WebSockets. Now SSE supports Opera 10.6+ (Opera 9 supports the old SSE standard), Chrome, Safari 5+. Firefox supports Multipart XMLHTTPRequest, for which you can write a wrapper and use it as an SSE interface.
Links
1. An online example of SSE chat can be viewed here:
sse-chat.nodester.comThis is a somewhat stripped-down version of the chat due to the peculiarities of Nodester proxying (there is no message about the number of users online and no messages about quitting the chat, there may be frequent reconnect)2. Sample
source :
github.com/azproduction/event-source-chat3.
Another SSE Tutorial4.
SpecificationPS It seems that the chat has covered habraeffekt, but something is possible with nodester (it often happens at it). If you are interested in the result, then download the
source from GitHub.
UPD Added Multipart XMLHTTPRequest, XMLHTTPRequest: Interactive thanks for the addition
yui_room9