HTTP server push, also known as HTTP stream, is a client-server communication mode that asynchronously pushes information from the HTTP server to the client without the client requesting it. Nowadays, web and APP use this communication mode in more and more scenarios, such as real-time message reminder, IM online chat, multi-person document collaboration and so on. In the past, this kind of functionality was typically implemented with Ajax long polling, but now we have new, more elegant options — WebSocket and SSE.

WebSocket is a protocol for full duplex communication over a single TCP connection provided by HTML5. In the WebSocket API, the browser and the server only need to do a handshake, and then a fast channel is formed between the browser and the server. Data can be transmitted directly between the two. The browser sends a request to the server to establish a WebSocket connection through JavaScript. After the connection is established, the client and server can exchange data directly through the TCP connection. When you get a Web Socket connection, you can send data to the server using the send() method and receive the data returned by the server using the onMessage event.

SSE, short for Server-Sent Events, is a single message push from Server to client (browser). The corresponding browser-side implementation Event Source interface is formulated as part of HTML5. IE doesn’t support this technology right now. Compared with WebSocket, SSE is much simpler, the workload of server side and client side is much smaller, much simpler, and the functions realized at the same time are also limited.

SSE&WebSocket

  • WebSocket is a full-duplex channel, two-way communication, more powerful; SSE is a one-way channel and can only be sent from the server to the browser.
  • WebSocket is a new protocol that requires server-side support. SSE is deployed on HTTP protocol, existing server software support.
  • SSE is a lightweight protocol and relatively simple; WebSocket is a heavy protocol and relatively complex.
  • SSE supports disconnection and reconnection by default, but WebSocket requires additional deployment.
  • SSE supports custom data types to be sent.
  • SSE does not support CORS, and the parameter URL is the server url, which must be in the same domain with the current web site, and the protocol and port must be the same. WebSocket support

The client EventSource

API

[Constructor(DOMString url, optional EventSourceInit eventSourceInitDict)]
interface EventSource : EventTarget {
  readonly attribute DOMString url;
  readonly attribute boolean withCredentials;

  // ready state
  const unsigned short CONNECTING = 0;
  const unsigned short OPEN = 1;
  const unsigned short CLOSED = 2;
  readonly attribute unsigned short readyState;

  // networking
  attribute EventHandler onopen;
  attribute EventHandler onmessage;
  attribute EventHandler onerror;

  void close();
};

dictionary EventSourceInit {
  boolean withCredentials = false;
};
Copy the code

Basic usage

  1. Create an EventSource instance
var source = new EventSource(url)
Copy the code
  1. Event listeners
// After the connection is established, the 'open' event is triggered
source.onopen = (event) = >{
  // ...
}

// A message is received, triggering the 'message' event
source.onmessage = (event) = >{
  // ...
}

// An error occurs and an 'error' event is raised
source.onerror = (event) = >{
  // ...
}

// Custom events
source.addEventListener('eventName', event => {
  // ...
}, false)
Copy the code
  1. Close the connection
source.close()
Copy the code

Server-side development

Response header Settings

Corresponding to SSE, you need to set the following Http header information

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Copy the code

On the first line, the CONTent-type specifies the MIME Type to be text/event-stream

The message format

The message pushed by SSE must be utF-8 encoded plain text. Each push consists of several event messages, and each event message is separated by two newlines (\n\n). Each event message consists of several lines, each in the form of a key-value pair:

[key]: value\n
Copy the code

Key has the following values

  • Data: message content
  • Event: Indicates the event name of a message. The default value is messageaddEventListener()Listen for the event.
  • Id: indicates the message id. The browser reads this value with the lastEventId property. Once the connection is broken, the browser sends an HTTP header containing a special last-event-ID header that sends back the value to help the server rebuild the connection. Therefore, this header can be thought of as a synchronization mechanism
  • Retry: Interval at which the browser retries the connection.

The sample

Browserside code

// index.js
var source = new EventSource('/stream');
source.onmessage = function(event) {
  var message = event.data; 
  // do stuff based on received message 
};
Copy the code

Server-side code (nodeJS)

var express = require('express')
var fs = require('fs')
var app = express()

app.get('/stream', (req, res) => {
  res.writeHead(200, {
    "Content-Type": "text/event-stream"."Cache-Control": "no-cache"."Connection": "keep-alive"
  });

  var interval = setInterval(function () {
    res.write("data: " + (new Date()) + "\n\n");
  }, 1000);

  req.connection.addListener("close".function () {
    clearInterval(interval);
  }, false);
})

app.listen(9999, (err) => {
  if (err) {
    console.log(err)
    return
  }
  console.log('listening on port 9999')})Copy the code

Pay attention to our