Objective
Recently in a project, need to use to WebSocket, before to WebSocket not very understanding, so took a little time to familiarize with WebSocket.
Between browser and server communication, traditional HTTP requests are not ideal in some scenarios, such as live chat, real-time games, etc.
It faces two main drawbacks:
- The "Real time" of the message cannot be achieved;
- Server can not actively push information;
Its main HTTP-based solutions are:
Ajax-based polling: the client periodically or dynamically within a short period of time to the server to request the interface, ask whether there is new information on the server, its shortcomings are obvious: redundant empty requests (waste of resources), data acquisition has a delay;
Long Poll: It uses a blocking scheme, the client initiates an AJAX request to the server, the server suspends the request, does not return data until there is new data, and the client receives the data and executes a Long Poll again; is unacceptable in a large number of connected scenarios;
As you can see, the HTTP protocol-based scenario contains an essential flaw, "passivity", where the server cannot push the message, and the client initiates the request to keep asking if there is a new message, and there is a performance drain on both the client and the server.
WebSocket is a network technology that HTML5 started to provide full duplex communication between the browser and the server. The WebSocket communication protocol was established as the standard RFC 6455,websocketapi by the IETF in 2011. In the WebSocket API, browsers and servers only need to act as a handshake, and then a fast channel is formed between the browser and the server. The data can be transmitted to each other directly between the two.
WebSocket is the new network protocol standard proposed in HTML5, which contains several features:
- The application layer based on TCP protocol;
- Once the connection is established (until the disconnection or error), the server will remain connected to the client after the handshake, which is a persistent connection;
- The server can actively distribute the message through the real-time channel;
- "Real-time (relative)" and "temporal" of data reception;
Practice
Using Websocket in a browser is very simple, providing native Websocekt objects in browsers that support Websocket, where the receipt of messages and the processing of data frames are already encapsulated in the browser.
Here is a simple example of how to use Websocekt;
The native class WebSocket is provided in the browser and instantiated with the New keyword:
WebSocket WebSocket(String url,optional String | [] protocols);
Receive two parameters:
- The URL indicates the address that needs to be connected, for example: ws://localhost:8080;
- Protocols optional parameter, can be a string or an array to represent the sub-protocol, so that a server can implement a variety of WebSocket sub-protocol;
Instantiating an object provides two methods:
- Send receives a string| arraybuffer| Blob data, sent as data to the server;
- Close receives an (optional) code (Close status number, default of 1000) and an (optional) string (which indicates the reason for disconnection), and the client disconnects actively;
Connection Status:
The WebSocket class provides some constants that indicate the state of the connection:
- Websocket.connecting 0 Connection is not turned on;
- Websocket.open 1 connection is turned on and ready for communication;
- Websocket.closing 3 Connection is in the process of shutting down;
Websocket.closed 4 The connection is closed or the connection cannot be established;
The ReadyState attribute is provided in the instance object of WebSocket to determine the current state;
The following event can be heard in the instantiated object:
- Open connection opens the callback event, when ReadyState becomes open;
- The message receives a callback event for the messages, and the callback function receives a messageevent data;
- Close connection closes the callback event, when ReadyState becomes CLOSED;
- Error establishing a callback event with errors in the connection process;
Code implementation
const ws = new WebSocket(‘ws://localhost:8080‘);let sendTimmer = null;let sendCount = 0;ws.onopen = function () { console.log(‘@open‘); sendCount++; ws.send(‘Hello Server!‘ + sendCount); sendTimmer = setInterval(function () { sendCount++; ws.send(‘Hi Server!‘ + sendCount); if (sendCount === 10) { ws.close(); } }, 2000);};ws.onmessage = function (e) { console.log(‘@message‘); console.log(e.data);};ws.onclose = function () { console.log(‘@close‘); sendTimmer && clearInterval(sendTimmer);};ws.onerror = function () { console.log(‘@error‘);};
Console to see
@open@messageHello Client@messagereceived: Hello Server!1(From Server)@messagereceived: Hi Server!2(From Server)@messagereceived: Hi Server!3(From Server)@messagereceived: Hi Server!4(From Server)@messagereceived: Hi Server!5(From Server)@messagereceived: Hi Server!6(From Server)@messagereceived: Hi Server!7(From Server)@messagereceived: Hi Server!8(From Server)@messagereceived: Hi Server!9(From Server)@close
The Open event is triggered first, and then every time the data service is sent, the message event is triggered, and the browser disconnects after sending 10 times, so the close event is triggered; the server reply is not received after the last send because the client disconnects immediately;
Of course, more specific data interactions can be seen from the network;
Events and data
There are two ways to listen to an WebSocket instance, with the message event as an example:
- Assign values directly to the OnMessage property, as above:
ws.onmessage = function () {};
- Use AddEventListener to listen for events such as:
ws.addEventListener(‘message‘, function () {});
Get the Messageevent type parameter E in the message callback function, the data we need can be obtained by E.data ;
One thing to note: Regardless of the server and client, the data it receives is a serialized string (and of course arraybuffer| Blob type data), many times we need to parse and process the data, for example JSON.parse(e.data)
;
Connection stability
Due to the complexity of the network environment, some situations will be disconnected or connection error, we need to listen to close or Error event in the abnormal disconnection and reconnect;
For some reason the browser does not respond to callback events at error, so it is prudent to open a timed task after open to determine the current connection state readyState, and attempt to reconnect in the event of an exception;
Heartbeat
The WebSocket specification defines the heartbeat mechanism in which one party can send a ping (opcode 0x9) message to the other party, and the other party should return Pong (0xA) as soon as possible after receiving the ping.
Heartbeat mechanism is used to detect the connection of the other side of the online state, so if there is no heartbeat, then can not determine that one side is still in the connection state, some network layer such as Nginx or browser layer will be actively disconnected,
In JavaScript, WebSocket does not open Ping/pong API, although the browser comes with a heartbeat processing, but different vendors implementation is not the same, so we need in the development time with the server to contract good one self-implemented heartbeat mechanism;
For example, in the browser, after detecting the Open event, start a scheduled task, each time the data sent 0x9 to the server, and the server returned 0xA as a response;
In practice, the timed task of a heartbeat is usually sent 15-20 seconds apart.
Network protocol
The previous article says that Websocket is built on top of TCP, so it has a relationship with the HTTP protocol.
The Websocket connection is divided into the connecting phase and the connection phase, which is related to HTTP during the connection phase, but not to HTTP during the connection phase.
Construction and connection Stage
From the browser's Network, locate the WS connection and you can see:
GeneralRequest URL:ws://localhost:8080/Request Method:GETStatus Code:101 Switching ProtocolsResponse HeadersHTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: py9bt3HbjicUUmFWJfI0nhGombo=Request HeadersGET ws://localhost:8080/ HTTP/1.1Host: localhost:8080Connection: UpgradePragma: no-cacheCache-Control: no-cacheUpgrade: websocketOrigin: http://localhost:8080Sec-WebSocket-Version: 13User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36DNT: 1Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7,la;q=0.6,ja;q=0.5Sec-WebSocket-Key: 2idFk3+96Hs5hh+c9GOQCg==Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
This is a standard HTTP request with a few more fields in the request header than our common HTTP request protocol:
Connection: UpgradeUpgrade: websocketSec-WebSocket-Version: 13Sec-WebSocket-Key: 2idFk3+96Hs5hh+c9GOQCg==Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Connection for Upgrade, Upgrade for WebSocket, said to inform Nginx and Apache and other servers The connection is not an HTTP connection, essentially a websocket, so the server will be forwarded to the corresponding Websocke T task processing;
Sec-websocket-key is a Base64 encode value, generated randomly by the browser, to verify the correctness of the server connection;
Sec-websocket-versio represents the version of the WebSocket service for use;
In the response header:
HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: py9bt3HbjicUUmFWJfI0nhGombo=
Can see its return status code of 101, indicating the switching protocol;
Upgrade and Connection used to reply to the client to indicate that the protocol has been switched successfully;
The Sec-websocket-accept field corresponds to the Sec-websocket-key and is used to verify the correctness of the service;
Connection phase
When the connection handshake is established via HTTP, the next step is the real Websocket connection, which is based on TCP transceiver data, Websocket encapsulation and open interface.
Wss
In the HTTP protocol, there are many times when HTTPS requests (HTTP + TCL) are required for encryption and security purposes;
Accordingly, in the Websocket protocol, it is also possible to use encrypted transmission of--WSS, such as wss://localhost:8080.
Use is also the same as HTTPS certificate, here is generally referred to Nginx and other service layer to do the certificate processing.
This article refers to the article: https://qiutc.me/post/websocket-guide.html
WebSocket User Guide