Recently, I met a scene in my work that requires the server to push messages. Here I summarize the harvest of collecting and organizing WebSocket related information.

1. An overview of the

1.1 Server Push

WebSocket, as a communication protocol, belongs to a server push technology, which is supported by IE10+.

There are more than one Server push technology, including short polling, long polling, WebSocket, server-sent Events (SSE), etc., each of which has its advantages and disadvantages:

# Short polling Long polling Websocket sse
Communication methods http http Communication based on TCP long connection http
triggered polling polling The event The event
advantages Good compatibility and fault tolerance, simple implementation Saves resources than short polling Full duplex communication protocol, low performance overhead, high security, has certain 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
Scope of application B/s service B/s service Online games, banking interactions and payments One-way push from server to client

Short polling is the simplest, and is often used in simple scenarios where an Ajax request is made at regular intervals. So what is a long poll?

Long Polling is an improvement made on the basis of Ajax Polling. It does not return an empty response when there is no update, and holds the connection until there is an update. The client sends an Ajax request to the server, and the server holds the connection after receiving the request, and then returns the response message and closes the connection until there is a new message. The client processes the response information before sending a new request to the server. It is a solution, but not the best technical solution.

If the short polling means that the client keeps calling the server to ask if there is any message, the server replies and hangs up immediately, waiting for the next call. Long polling means that the client keeps making calls, and the server does not hang up after receiving a call. When there is a message, the client replies and hangs up.

Server-sent Events (SSE) is similar to long polling except that each connection sends more than one message. The client sends a request, and the server holds the connection until a new message is sent back to the client, so that the connection can support the message being sent again, one-way from the server to the client. However, IE is not supported until 11, without further ado….

1.2 WebSocket Features

The reason why websockets are needed when you already have polling is because short and long polling have a drawback: communication can only be initiated by the client.

If the back end wants to push messages to the front end, the front end needs to poll constantly to check whether the back end has new messages, which is inefficient and wastes resources (setInterval or setTimeout must be kept to connect, or HTTP connection is always open). WebSocket provides a civilized and elegant full-duplex communication solution. It is generally suitable for scenarios with strong real-time requirements on data, such as communication, stock, live broadcast and shared desktop, especially for frequent interactions between clients and services, such as chat rooms, real-time sharing, multi-person collaboration and other platforms.

The characteristics of

  1. Based on TCP protocol, the implementation of the server side is relatively easy.
  2. It has good compatibility with HTTP protocol. The default ports are also 80 and 443, and the handshake phase uses HTTP protocol, so it is not easy to mask the handshake and can pass various HTTP proxy servers.
  3. The data format is relatively light, with low performance overhead and high communication efficiency. The header information exchanged between the server and client is only about 2 bytes;
  4. You can send text or binary data.
  5. There are no same-origin restrictions, and clients can communicate with any server.
  6. The protocol identifier isws(WSS if encrypted), the server URL is the URL. Ex:ws://example.com:80/some/path
  7. Do not frequently create and destroy TCP requests, reduce the occupation of network bandwidth resources, and save server resources.
  8. WebSocket is purely event-driven, and once a connection is established, it listens for events to handle incoming data and changing connection state, all in the form of a sequence of frames. After the server sends the data, messages and events arrive asynchronously.
  9. No timeout processing.

HTTP and WS protocol structure

The WebSocket protocol identifier is represented by WS. The WSS protocol represents the encrypted WebSocket protocol, corresponding to HTTPs. The structure is as follows:

  • HTTP: TCP > HTTP
  • HTTPS: TCP > TLS > HTTP
  • WS: TCP > WS
  • WSS: TCP > TLS > WS

2 WebSocket communication process

First, Websocket is a persistent protocol, as opposed to HTTP, which is not persistent.

An HTTP communication lifecycle is defined by a Request, i.e., a Request and a Response. In HTTP1.0, the HTTP Request ends. Improved in HTTP1.1 with a keep-alive, multiple requests can be sent and multiple responses received within an HTTP connection, i.e. multiple requests can be merged. However, a Request can only correspond to one Response, which is passive and cannot be initiated actively.

Websocket is actually a new protocol, but in order to comply with the existing browser handshake specification borrows HTTP protocol to do part of the handshake.

WebSocket is purely event-driven, and once a connection is established, it listens for events to handle incoming data and changing connection state, all in the form of a sequence of frames. After the server sends the data, messages and events arrive asynchronously. WebSocket programming follows an asynchronous programming model that simply adds callbacks to WebSocket objects to listen for events.

2.1 WebSocket Communication flow chart

Here you can see the difference between the flow of traditional HTTP communication and WebSocket communication. The following figure shows what the browser and the server do in the three main steps of WebSocket.

2.2 Handshake for establishing a connection

When a Web application invokes the New WebSocket(URL) interface, the client begins the process of establishing a handshake connection with the WebServer at the URL address.

  1. The client establishes a connection with the server using a TCP three-way handshake, and if this connection fails, the subsequent process is not executed and the Web application is notified of an error message.
  2. After the TCP connection is successfully established, the client sends the WebSocket version number, protocol version number, original address, host address and other columns to the server through HTTP.
  3. After receiving the handshake request from the client, if the data and format of the packet are correct and the protocol version number of the client and the server match, the server accepts the handshake connection and sends the corresponding data reply, which is also transmitted through HTTP.
  4. If the content and format of the packet are correct after the client receives the packet from the server, the connection is successful and the packet is triggeredonopenAt this point, the Web developer can pass throughsend()Sends data to the server. Otherwise, the handshake connection fails and the Web application firesonerrorAnd can know the cause of connection failure.

This handshake looks like HTTP but is not, allowing the server to interpret part of the Handshake request as HTTP and then switch to webSocket.

2.3 WebSocket Handshake Packets

A browser sends a WebSocket request message similar to:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
Copy the code

According to the HTTP1.1 protocol, the Upgrade header information represents the transfer of the communication protocol from HTTP/1.1 to the protocol specified by this item.

  • Connection: UpgradeIndicates that the browser notifies the server, if possible, to upgrade to the webSocket protocol.
  • OriginUse to verify that the browser domain name is within the scope of the server’s license.
  • Sec-WebSocket-KeyIs the key used for the handshake protocol and is a random 16-byte base64-encoded string generated by the browser.
  • Sec-WebSocket-ProtocolIs a user-defined string used to distinguish between protocols required by different services under the same URL.
  • Sec-WebSocket-VersionIs to tell the server the version of the protocol used.

WebSocket reply packet on the server:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Origin: null
Sec-WebSocket-Location: ws://example.com/
Copy the code
  • The same goes for the server sideConnection: UpgradeNotifies the browser that the server has successfully switched protocols.
  • Sec-WebSocket-AcceptIt was authenticated and encrypted by the serverSec-WebSocket-Key.
  • Sec-WebSocket-LocationRepresents the WebSocket URL to communicate with.
  • Sec-WebSocket-ProtocolIndicates the final protocol to be used.

After such a handshake similar to HTTP communication, it is time to communicate using the WebSocket protocol. There is no HTTP communication between the client and the server, and the WebSocket protocol takes over.

3. WebSocket API

The browser provides an implementation of a WebSocket object that can be used to create and manage WebSocket connections, and to send and receive data over the connection. WebSocket is event-driven, so simply add a callback function to the WebSocket object to listen for events.

As with XMLHttpRequest, we use this constructor to create an instance of the object const ws = new WebSocket(‘ws://localhost:8080’) using properties and methods mounted under the object. The following articles use WS to refer to instances of WebSocket.

To view the DEMO

3.1 Common attributes on WS

ws.readyState

The WebSocket instance object, similar to XHR, has a read-only property readyState to indicate the current state of the connection:

state value describe
CONNECTING 0 The connection is not open yet.
OPEN 1 The connection is open and ready to communicate.
CLOSING 2 The connection is being closed.
CLOSED 3 The connection was closed or could not be established.

An example:

switch (ws.readyState) {
  case WebSocket.CONNECTING:
    // ...
    break;
  case WebSocket.OPEN:
    // ...
    break;
  case WebSocket.CLOSING:
    // ...
    break;
  case WebSocket.CLOSED:
    // ...
    break;
  default:
    // this never happens
    break;
}
Copy the code

ws.onopen / ws.onclose

The onopen property of the instance object, which specifies the callback function if the connection is successful.

ws.onopen = function () {
  ws.send('Hello Server! ');
}
Copy the code

If you want to specify multiple callback functions, you can use addEventListener.

ws.addEventListener('open'.function (event) {
  ws.send('Hello Server! ');
});
Copy the code

The onClose property of the instance object, which specifies the callback function if the connection is closed.

ws.onclose = function(event) {
    const { code, reason, wasClean} = event
    // ...
};
ws.addEventListener('close'.function(event) {
    const { code, reason, wasClean} = event
    // ...
})
Copy the code

ws.onmessage

The onMessage property of the instance object, which specifies the callback function to receive data from the server.

ws.onmessage = function(event) {
  const { data } = event;
  // ...
};
ws.addEventListener('message'.function(event) {
  const { data } = event; 
  // ...
});
Copy the code

Note that the server data can be textual or binary (bloB objects or Arraybuffer objects).

ws.onmessage = function(event){
  if(typeof event.data === String) {
    // string
  }
  if(event.data instanceof ArrayBuffer) {const { data: buffer } = event;
    // array buffer}}Copy the code

In addition to dynamically determining the data type received, you can explicitly specify the binary data type received using the binaryType attribute. The value of binaryType should be ‘blob’ or ‘arrayBuffer’, where ‘blob’ indicates the use of bloB objects and ‘ArrayBuffer’ indicates the use of arrayBuffer objects.

ws.binaryType = 'blob';                // Blob data is received
ws.onmessage = function(e) {
  console.log(e.data.size);
};

ws.binaryType = 'arraybuffer';            // Receive ArrayBuffer data
ws.onmessage = function(e) {
  console.log(e.data.byteLength);
};
Copy the code

To view the DEMO

ws.bufferedAmount

The bufferedAmount read-only property of the instance object, indicating how many bytes of binary data remain unsent. It can be used to determine whether the transmission is complete. This value is reset to 0 after all queue data has been sent and is not set to 0 when the connection is closed. If you keep calling send(), this value will keep growing.

var data = new ArrayBuffer(10000000);
ws.send(data);
if (ws.bufferedAmount === 0) {
  // Send complete
} else {
  // Send is not finished yet
}
Copy the code

ws.onerror

The onError property of the instance object, which specifies the callback function when an error is reported.

ws.onerror = function(event) {
  // handle error event
};
ws.addEventListener("error".function(event) {
  // handle error event
});
Copy the code

3.2 Common methods on WS

ws.close()

Close a WebSocket connection or stop an ongoing connection request. This method has no effect if the connection is already in a Closed state.

ws.send()

The send() method of the instance object is used to send data to the server.

ws.send('your message');                // Send text examples

var file = document
  .querySelector('input[type="file"]')
  .files[0];
ws.send(file);                            // Send an example of Blob objects

// Sending canvas ImageData as ArrayBuffer   
var img = canvas_context.getImageData(0.0.400.320);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
  binary[i] = img.data[i];
}
ws.send(binary.buffer);                // Send an example of an ArrayBuffer object
Copy the code

The last instance of canvas_context in the ArrayBuffer object container is an object of type CanvasRenderingContext2D on which the.getimageData () method returns an ImageData object.


Online posts are mostly different in depth, even some inconsistent, the following article is a summary of the learning process, if you find mistakes, welcome to comment out ~

Reference:

  1. Ruan Yifeng – WebSocket tutorial
  2. A brief introduction to several Web server side push technologies
  3. Dry goods | long connection/websocket/SSE mainstream server push technology and compared
  4. Sf-websocket details
  5. WebSocket – JavaScript examples
  6. JavaScript WebSocket technology
  7. What is the principle of WebSocket? Why can persistent connection be implemented?
  8. The Socket and WebSocket

Official documents:

  1. MDN – WebSocket
  2. W3C – The WebSocket API
  3. Rfc-websocket protocol stack

Tools:

  1. WebSocket online test

PS: Welcome to pay attention to my official account [front-end afternoon tea], come on together

In addition, you can join the “front-end afternoon tea Exchange Group” wechat group, long press to identify the following TWO-DIMENSIONAL code to add my friend, remarks add group, I pull you into the group ~