Writing in the front
WebSocket is a technology that allows the server to actively push data to the client. A few days ago, I wrote a log function, and the log data needs to be updated in real time. There is a WebSocket component encapsulated in the project, and the interface supports WebSocket, it is implemented. This is also the first time to use it. I briefly researched it and shared it. Sample article code here: github.com/neroneroffy…
What is the WebSocket
First, you need to understand the concept of webSocket. Here is wikipedia’s explanation
WebSocket is a communication protocol that enables full-duplex communication over a single TCP connection. WebSocket makes it easier to exchange data between the client and the server, allowing the server to actively push data to the client. In the WebSocket API, the browser and server only need to complete a handshake to establish a persistent connection and two-way data transfer.
First of all, it is important to understand that WebSocket is a communication protocol, which is different from HTTP protocol. HTTP protocol can only realize the single communication of client request and server response. WebSocket can achieve two-way communication between the client and the server. To put it bluntly, the biggest and most obvious difference is that the server can actively push the message to the client. The remaining features are:
- The handshake phase adopts HTTP protocol.
- Lightweight data format with low performance overhead. When the client exchanges data with the server, the data header from the server to the client is 2 to 10 bytes, and the mask from the client to the server needs to be added with another 4 bytes. HTTP needs to carry the full header each time.
- Better binary support, can send text, and binary data.
- There are no same-origin restrictions, and clients can communicate with any server.
- The protocol identifier is WS (or WSS if encrypted), and the requested address is the backend WebSocket-enabled API.
Several ways to communicate with the server in real time
As we all know, there are generally two ways to interact with a server in real time without using websockets. AJAX Polling and Long Polling.
AJAX polling
AJAX polling is a timed request, which is the normal client-server communication process, but is sent in an infinite loop, so that the server can ensure that the latest information, the client can be retrieved.
Long Polling Long Polling
Long Polling means that the client maintains a Long connection with the browser and disconnects when the server returns a message. And then reconnect. It’s a circular process.
The client initiates a Long Polling. If the server has no data to return, it holds the request and returns it to the client when it has data. The client then launches another Long Polling and repeats the process again.
disadvantages
Both of these methods have a fatal weakness: too much overhead and passivity. This is a test for the server, assuming high concurrency. WebSocket features such as handshake, persistent connection, and active push can solve these problems without sacrificing performance.
WebSocket connection process
The client initiates an HTTP handshake and tells the server to communicate with WebSocket and the version of the WebSocket protocol. The server verifies the protocol version and upgrades it to WebSocket. If any data needs to be pushed, it will be actively pushed to the client.
At the beginning of the connection, the client uses HTTP and the server upgrade protocol. After the upgrade, the subsequent data exchange follows the WebSocket protocol. Let’s look at Request Headers
Accept-Encoding: gzip, deflate, br Accept-Language: zh,zh-TW; Q = 0.9, en - US; Q = 0.8, en. Q = 0.7, useful - CN; Q =0.6 cache-control: no-cache Connection: Upgrade Host: 127.0.0.1:3000 Origin: http://localhost:3000 Pragma: no-cache Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits Sec-WebSocket-Key: bwb9SFiJONXhQ/A4pLaXIg== Sec-WebSocket-Version: 13 Upgrade: websocketCopy the code
The key fields are these:
- Connection: Upgrade Indicates that the protocol is to be upgraded
- Upgrade: websocket needs to be upgraded to the WebSocket protocol
- Sec-websocket-version Indicates the WebSocket Version. If the server does not support the version, you need to return an sec-websocket-versionheader containing the version number supported by the server.
- Sec-websocket-key corresponds to the SEC-websocket-accept of the server response header. Since there is no origin restriction, the WebSocket client can connect to any service that supports WebSocket. This is like a key and a lock, avoiding redundant, meaningless connections.
Take a look at the Response Headers that the server responds to
Connection: Upgrade
Sec-WebSocket-Accept: 2jrbCWSCPlzPtxarlGTp4Y8XD20=
Upgrade: websocket
Copy the code
The key is this field
- Sec-websocket-accept: Indicates that the server is willing to initiate a WebSocket connection. The value is calculated based on the sec-websocket-key in the client request header
WebSocket API
If a client wants to communicate with a Webscoket-enabled server, it can use the WebSocket constructor to return a WebSocket object.
const ws = new WebSocket("ws://localhost:3000/websocket");
Copy the code
The client will then connect to the server.
Properties of the returned instance object:
- Websocket. onopen: Callback after successful connection
- Websocket. onclose: Callback after the connection is closed
- Websocket. onerror: Callback after connection failure
- Websocket. onMessage: Callback to server data received by the client
- Websocket. bufferedAmount: Number of binary bytes not sent to the server
- Websocket. binaryType: Uses binary data types to connect
- Websocket. protocol: subordinate protocol selected by the server
- Websocket. url: indicates the absolute path of the WebSocket
- Websocket. readyState: four constants corresponding to the current connection state
The name of the | value |
---|---|
WebSocket.CONNECTING | 0 |
WebSocket.OPEN | 1 |
WebSocket.CLOSING | 2 |
WebSocket.CLOSED | 3 |
Methods:
- Websocket.close () closes the current connection
- Websocket. send(data) Sends data to the server
The sample
Now that I’ve talked about all these concepts, I can finally see how it works. WebSocket communication requires the cooperation of the client and the server.
I wrote an example, after the server starts the connection, the timer is used to actively send random numbers to the client, the client can also send a message to the server, and then the server returns this message to the client. The client is JS + HTML, the server used express + Express-WS to achieve. The code is here: github.com/neroneroffy… . Clone down, install dependencies, and run NPM start to see the effect.
The client
Front-end page, the final effect is as shown in the above renderings:
<body>
<div class="websocket">
<div class="receive"> <p> The message returned by the server </p> <div id="receive-box"></div>
</div>
<div class="send">
<textarea type="text" id="msg-need-send"></textarea>
<p>
<button id="send-btn"</button> </p> </div> <button ID ="exit"</button> </div> </body>Copy the code
Js, the code to use webSocket is all here. All you do is bind events to the elements of the page. The WebSocket object is then created to listen for events such as the connection, receiving messages, and closing of the object, feeding the data back to the page
const msgBox = document.getElementById("msg-need-send")
const sendBtn = document.getElementById("send-btn")
const exit = document.getElementById("exit")
const receiveBox = document.getElementById("receive-box"// Create a webSocket object const ws = new webSocket (Ws: / / "127.0.0.1:3000 / websocket/test") ws.onopen = e => {// Connect after listening console.log(' WebSocket connection status:${ws.readyState}ReceiveBox. InnerHTML += '<p>${data.data}</p>`
receiveBox.scrollTo({
top: receiveBox.scrollHeight,
behavior: "smooth"})} ws.onclose = data => {// Listen connection close console.log("WebSocket connection closed") console.log(data); } sendBtn.onclick = () => {// Click the send button. Ws.send (msgbox.value)} exit.onclick = () => {// Client automatically closes connection ws.close()}Copy the code
The service side
With modular development in mind, you don’t put code directly into files that create services directly. Instead, routing is used to assign a separate interface to the webSocket service
const express = require("express");
const expressWs = require("express-ws")
const router = express.Router()
expressWs(router);
router.ws("/test", (ws, req) => {
ws.send("Connection successful")
letInterval // After the connection is successful, use a timer to send data to the client periodically. Pay attention to the timing of the timer. Data can be sent only when the connection is enabledsetInterval(() => {
if (ws.readyState === ws.OPEN) {
ws.send(Math.random().toFixed(2))
} else{clearInterval(interval)}}, 1000) {clearInterval(interval)}}, 1000)"message", msg => {
ws.send(msg)
})
})
module.exports = router
Copy the code
Finally, look at the process of data interaction
conclusion
The above simple implementation of a webSocket communication. There are many practical things, such as webSocket extension, heartbeat detection, data encryption, identity authentication and other knowledge points. But I also need to study, so I won’t do the introduction.
Related articles
WebSocket protocol: 5 minutes from beginner to master
WebSocket tutorial — Ruan Yifeng
WebSocket API
Express – ws document
Welcome to pay attention to my public number: a front-end, share my understanding of the front-end knowledge from time to time