Introduction to the

Web Sockets define a channel for full-duplex communication over a network over a single socket. Just an incremental improvement over traditional HTTP communication, and a leap forward especially for real-time, event-driven applications. Polling(Polling), long-polling (Long Polling), Websocket, SSE. Four Web instant messaging technologies compare their implementation methods and their advantages and disadvantages. The advantages and disadvantages are as follows:

# Polling (Polling) Long Polling (Long – Polling) Websocket sse
Communication protocol http http tcp http
triggered Client Client Client, server(client, server) Client, server(client, server)
advantages Good compatibility and fault tolerance, simple implementation Saves resources than short polling Full duplex communication protocol, low performance overhead, high security, scalability The realization is simple and the development cost is low
disadvantages Poor security, occupying more memory resources and requests Poor security, occupying more memory resources and requests Data transmission requires secondary parsing, which increases the cost and difficulty of development Only applicable to advanced browsers
delay Non-real-time, latency depends on the request interval With short polling real-time Non-real-time, the default delay is 3 seconds, the delay can be customized

The above basically contains the advantages and disadvantages of each implementation, which protocol they are based on, and which end actively sends data.

Polling (Polling)

Short Polling (Polling) is achieved by the browser sending HTTP requests to the server every few seconds. The server responds directly to the request regardless of whether there is any data update. When the server response is complete, the Tcp connection is closed, as shown below:

Example code implementation is as follows:

function Polling() {
    fetch(url).then(data= > {
        // somthing
    }).catch(err= > {
        console.log(err);
    });
}
setInterval(polling, 5000);
Copy the code
  • Advantages: As you can see, the implementation is very simple and compatible as long as HTTP is supported.
  • Disadvantages: But its disadvantages are also obvious that it is very resource-consuming because of the buildTcpThe connection is very resource-intensive and will be closed as soon as the server respondsTcpConnect, and the next request is re-establishedTcpThe connection.

COMET

**Alex Russell (Lead project for the Dojo Toolkit) ** calls this “server push” technique based on HTTP long connections without installing plug-ins on the browser side “Comet.” COMET is commonly used in two different ways: http-based long-polling techniques and iframe-based stream patterns.

Long Polling (long-polling)

After the client sends a request, the server will not immediately return data. The server will block the request and the connection will not be disconnected immediately. The connection will not be returned until the server has data update or the connection times out. The general effect is as follows:

The client code is as follows:

function LongPolling() {
    fetch(url).then(data= > {
        LongPolling();
    }).catch(err= > {
        LongPolling();
        console.log(err);
    });
}
LongPolling();
Copy the code
  • Advantages: Compared with short polling, long polling significantly reduces the number of unnecessary HTTP requests and saves resources.
  • Disadvantages: Suspended connections can also lead to waste of resources.

Stream mode based on iframe

When we embed an iframe in the page and set its SRC, the server can “stream” content to the client over a long connection. For example, we can return javascript code wrapped in a Script tag to the client, and that code will be executed in the iframe. Therefore, if we define a handler function, process(), in the parent page of the iframe in advance and write it in the connection response every time there is new data to push. The code in the iframe then calls the process() function defined in the parent page. (Isn’t it a bit like the way JSONP transfers data?)

  // Data processing methods defined in the parent page
  function process(data) {
      // do something
  }

  // Create an invisible iframe
  var iframe = document.createElement('iframe');
  iframe.style = 'display: none';
  // SRC points to the back-end interface
  iframe.src = '/long_iframe';
  document.body.appendChild(iframe);
Copy the code

Node is used as an example for the back-end

const app = http.createServer((req, res) = > {
    // A method to return data, which is assembled into a script and returned to iframe
    const iframeSend = data= > {
        let script = `<script type="text/javascript">
                        parent.process(The ${JSON.stringify(data)})
                    </script>`;
        res.write(script);
    };

    res.setHeader('connection'.'keep-alive');
    // Note that the content-type of the corresponding header is set
    res.setHeader('content-type'.'text/html; charset=utf-8');        
    // When data is updated, the server "pushes" data to the client
    EVENT.addListener(MSG_POST, iframeSend);

    req.socket.on('close', () = > {console.log('iframe socket close');
        // Remove the listener when the connection is closed to avoid memory leaks
        EVENT.removeListener(MSG_POST, iframeSend);
    });
});

Copy the code

The effect is as follows:

However, there is a slight flaw in using iframe, so the iframe is never loaded, so the browser will always have a loading flag.

His pros and cons are the same as the long poll above.

Websocket

Some features of WebSocket and basic use methods are not described here, please see another blog WebSocket (a) analysis; The approximate code is as follows: server

    const express = require('express');
    const app = express();
    const server = require('http').Server(app);
    const WebSocket = require('ws');

    const wss = new WebSocket.Server({port: 8080});
    wss.on('connection'.function connection(ws) {
        console.log('server: receive connection');
        ws.on('message'.function incoming(message) {
            console.log('server: recevied: %s', message);
        });
        ws.send('world');
    });

    app.get('/'.function (req, res) {
        res.sendfile(__dirname + '/index.html');
    });
    app.listen(3000);
Copy the code

The client

    const ws = new WebSocket('ws://localhost:8080');
    ws.onopen = function () {
        console.log('ws onopen');
        ws.send('from client:hello');
    };
    ws.onmessage = function (e) {
        console.log('ws onmessage');
        console.log('from server:' + e.data);
    }
Copy the code

The running effect is as follows:

  • Advantages: No waste of performance
  • Cons: Learning a new request library

SSE (Server-Sent Events)

Server-sent is a standard proposed by HTML5. The client initiates a TCP connection with the server and maintains the connection until either the client or the server disconnects. ServerSent uses a “ask “+” answer” mechanism. After the connection is created, the browser periodically sends a message to the server asking if it has a message of its own. This implementation is similar to the iframe-based long connection pattern we mentioned in the previous section. HTTP responses have a special content-type — text/event-stream. This header identifies the response as an event stream. The client does not close the connection, but waits for the server to continuously send the response. The SSE specification is relatively simple, mainly divided into two parts: the EventSource object in the browser, and the communication protocol between the server and the browser.

Basic usage

The object can be created in the browser using the EventSource constructor

  var source = new EventSource('/sse');
Copy the code

The response content of SSE can be regarded as an event flow, which is composed of different events. These events trigger methods on the front-end EventSource object.

  // The default event
  source.addEventListener('message'.function (e) {
      console.log(e.data);
  }, false);

  // User-defined event name
  source.addEventListener('my_msg'.function (e) {
      process(e.data);
  }, false);

  // The listener connection is open
  source.addEventListener('open'.function (e) {
      console.log('open sse');
  }, false);

  // Listening error
  source.addEventListener('error'.function (e) {
      console.log('error');
  });
Copy the code

EventSource works by listening for events. Note that the above code listens for y_MSG events. SSE supports custom events. The default event listens for message to get data. The implementation code is as follows:

The client

  // Displays chat information
  let chat = new EventSource("/chat-room");
  chat.onmessage = function (event) {
      let msg = event.data;
      $(".list-group").append("<li class='list-group-item'>" + msg + "</li>");
      // chat.close(); Shut down the server - sent the event
  };

  // Custom events
  chat.addEventListener("myChatEvent".function (event) {
      let msg = event.data;
      $(".list-group").append("<li class='list-group-item'>" + msg + "</li>");
  });
Copy the code

The service side nodejs

  var express = require('express');
  var router = express.Router();
  router.get('/chat-room'.function (req, res, next) {
      // When res.white's data ends with \n\n, the message is sent by default, triggering onMessage. \r\n does not trigger onMessage
      res.header({
          "Content-Type": "text/event-stream"."Cache-Control": "no-cache"."Connection": "keep-alive"
      });

      // res.white("event: myChatEvent\r\n"); Custom events
      res.write("retry: 10000\r\n"); // Specifies the maximum interval for communication
      res.write("data: start~~\n\n");
      res.end(); // Not adding end does not assume that the end of the data transfer will result in no next request
  });
Copy the code
  • Advantage: The client only needs to connect once, and the Server periodically pushes the connection, unless one end is disconnected. And SSE will automatically reconnect if the connection is accidentally disconnected.
  • Cons: New grammar to learn

conclusion

The comparison of the above four Web instant messaging technologies can be considered from different perspectives and their priorities are different. Basically, they can be divided into two categories: communication based on HTTP and TCP.

Compatibility considerations: Short polling > Long polling > long SSE>WebSocket

In terms of performance: WebSocket> long connection SSE> Long polling > short polling

Server push: WebSocket> Long Connection SSE> Long polling

reference

All kinds of “server push technology principle and instance (Polling/COMET/SSE/WebSocket)

JavaScript server push technology WebSocket

Polling, long polling, long connection, WebSocket

Message push mechanism – Polling, long polling, Server Sent Event (SSE) and WebSocket (WS)