SSE (Server Sent Event) message push

SSE (Server Sent Event) message push

Message push means that the server and the client actively push messages.

The nature of SSE

Strictly speaking, the HTTP protocol cannot enable the server to actively push information. However, there is a workaround where the server declares to the client that the next thing to send is streaming. That is to say, what is sent is not a one-time data packet, but a data stream, which will be sent continuously. At this time, the client will not close the connection, but will always wait for the new data stream sent by the server. Video playback is an example of this. Essentially, this kind of communication is to complete a long download in the form of streaming information. SSE uses this mechanism to push information to the browser using streaming information. SSE is based on the persistent connection in the HTTP protocol . It has the network protocol and EventSource client interface standardized by W3C. As part of the HTML5 standard suite, it is currently supported by other browsers except IE/Edge.

The difference between SSE and websockets

  1. SSE is based on the HTTP protocol, and websocket is based on the websocket protocol.
  2. SSE is lighter than websocket and easier to use.
  3. SSE supports disconnection reconnection by default, while websocket needs to implement disconnection reconnection by itself.
  4. SSE transmits data in text, while websocket transmits in binary.
  5. SSE supports custom message types sent.
  6. SSE is a one-way channel that can only be sent from the server to the browser, while WebSocket is a full-duplex channel that can communicate in both directions, so it is more powerful and flexible.

Client API

  1. SSE's client API is deployed on the EventSource object. Detect whether the browser supports SSE before use
if ('EventSource' in window) {
    
    }
  1. The browser generates an EventSource instance and initiates a connection to the server. The url can be in the same domain as the current URL, or across domains. When cross-domain, you can specify the second parameter to open the withCredentials attribute, indicating whether to send cookies together.
var source = new EventSource(url,{
    
     withCredentials: true });
  1. The readyState property of the EventSource instance indicates the current state of the connection. This property is read-only and can take the following values:

0: Equivalent to the constant EventSource.CONNECTING, indicating that the connection has not been established, or the disconnection is being reconnected.
1: Equivalent to the constant EventSource.OPEN, indicating that the connection has been established and data can be accepted.
2: Equivalent to the constant EventSource.CLOSED, indicating that the connection has been disconnected and will not reconnect.

  1. Once the connection is established, the open event will be triggered, and the callback function can be defined in the onopen attribute.
// 写法一
source.onopen = function (event) {
    
    
  
};
// 写法二
source.addEventListener('open', function (event) {
    
    

}, false);
  1. When the client receives the data sent by the server, it will trigger the message event, which can be used in the callback function of the onmessage attribute.
// 写法一
source.onmessage = function (event) {
    
    
  var data = event.data;
  
};
// 写法二
source.addEventListener('message', function (event) {
    
    
  var data = event.data;
}, false);
  1. If a communication error occurs (such as a connection interruption), the error event will be triggered, and the callback function can be defined in the onerror attribute.
// 写法一
source.onerror = function (event) {
    
    
  
};
// 写法二
source.addEventListener('error', function (event) {
    
    
 
}, false);
  1. The close method is used to close the SSE connection.
source.close();
  1. By default, the data sent by the server always triggers the message event of the browser EventSource instance. Developers can also customize SSE events. In this case, the data sent back will not trigger the message event.
source.addEventListener('自定义 SSE 事件', function (event) {
    
    
  var data = event.data;
}, false);

client example

sse package

class SseClient {
    
    
  sseUrl = ''
  source = null;
  openCallback = null;
  errorCallback = null;
  messageCallback = null;
  constructor(sseUrl, openCallback, errorCallback, messageCallback) {
    
    
    this.sseUrl = sseUrl
    this.openCallback = openCallback
    this.errorCallback = errorCallback
    this.messageCallback = messageCallback
    this.connect()
  }
  connect() {
    
    
    if ('EventSource' in window) {
    
    
      // sseUrl可以与当前网址同域,也可以跨域。跨域时,可以指定第二个参数,打开withCredentials属性,表示是否一起发送 Cookie
      this.source = new EventSource(this.sseUrl)
      // 连接一旦建立,就会触发open事件,可以在onopen属性定义回调函数
      this.source.onopen = (event) => {
    
    
        this.open(event)
      }
      // 如果发生通信错误(比如连接中断),就会触发error事件,可以在onerror属性定义回调函数。
      this.source.onerror = (event) => {
    
    
        this.error(event)
      }
      // 客户端收到服务器发来的数据,就会触发message事件,可以在onmessage属性的回调函数
      this.source.onmessage = (event) => {
    
    
        this.message(event)
      }
    } else {
    
    
      alert('当前浏览器不支持SSE!')
    }
  }
  open(event) {
    
    
    this.openCallback && this.openCallback(event)
  }
  error(event) {
    
    
    this.errorCallback && this.errorCallback(event)
  }
  message(event) {
    
    
    this.messageCallback && this.messageCallback(event)
  }
}

/**
 * 监听SSE的通用方法
 * @param sseUrl:SSE的连接地址
 * @param openCallback:SSE连接成功建立时的回调函数
 * @param errorCallback:SSE发生通信错误时的回调函数
 * @param messageCallback:客户端收到服务器发来数据时的回调函数
 * @returns {SseClient}
 */
export default (sseUrl, openCallback, errorCallback, messageCallback) => {
    
    
  return new SseClient(sseUrl, openCallback, errorCallback, messageCallback)
}

transfer

    connectSSE() {
      this.sse = SseClient('http://127.0.0.1:8844/stream', this.open, this.error, this.message)
    },
    open(event) {
      console.log('open', event)
    },
    error(event) {
      console.log('error', event)
    },
    message({ data }) {
      console.log(data)
    },

Node server example

var http = require("http");
http.createServer(function (req, res) {
    
    
  var fileName = "." + req.url;

  if (fileName === "./stream") {
    
    
    res.writeHead(200, {
    
    
      "Content-Type":"text/event-stream",
      "Cache-Control":"no-cache",
      "Connection":"keep-alive",
      "Access-Control-Allow-Origin": '*',
    });
    // 服务器可以用retry字段,指定浏览器重新发起连接的时间间隔
    res.write("retry: 10000\n"); 
    // event字段表示自定义的事件类型,默认是message事件。浏览器可以用addEventListener()监听该事件。
    // 自定义connecttime事件
    res.write("event: connecttime\n");
    // 数据内容用data字段表示。
    res.write("data: " + (new Date()) + "\n\n");
    res.write("data: " + (new Date()) + "\n\n");

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

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

Front-end related dependencies

vue-sse

reference link

  1. SSE
  2. SSE

Guess you like

Origin blog.csdn.net/weixin_39893889/article/details/130290442