“This is the first day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Since I have been exposed to many B/S structure projects, I hope to build a project with C/S structure, and socket communication is mostly used for this. This article will mainly introduce the client and server to establish WebSocket connection, message encapsulation, message encryption, and some common problems.

The concept is introduced

WebSocket

Traditional Http requests are stateless. Each request can only be initiated by one party, and the other party finishes the response after receiving the message. For frequent interactions, such as chat rooms, and projects that need real-time updates, the previous implementation adopts polling, and sends requests to the server every very short period of time to update new content. It is very time consuming and resource consuming to establish handshake connections and close each time.

WebSocket protocol is generated on the basis of Http 1.1 protocol, which solves the above problems of Http and can carry out full-duplex TCP communication. You only need to establish a handshake connection once, and then you can maintain a communication channel that listens for message events to send messages.

It should be noted that WebSocket message transmission is segmentially sent in the form of Frame Frame, and the obtained result is generally a string. Therefore, to transmit objects, arrays and other structures, serialization and deserialization are required.

The target

Personal practice will build a client-server robot communication project.

The server parses the custom DSL script for word segmentation/AST parsing; Different communication takes place depending on the client’s response. The back-end WS module is used for communication.

Domain Specific Languages (DSLS) can provide a relatively simple grammar for domain-specific business process customization.

The client is human-computer interaction, and the user communicates with the robot. Mainly use Html5 native Websocket for communication, which is different from the use of WS modules.

Usage is introduced

Html5 WebSocket and WS modules are used differently, and may not be the same for the data retrieved.

The division and use of state are the same for both. The status code can be obtained through ws. ReadyState:

ws.CONNECTING === 0;
ws.OPEN === 1;
ws.CLOSING === 2;
ws.CLOSED === 3;
Copy the code

Html5 WebSocket

Establish a connection

The character string is the WS address: ws://…

let ws = new WebSocket('ws://localhost:8080');
Copy the code

Receives the message

ws.onmessage = function(event){
    let msg = event.data;
    // ...
}
Copy the code

It is important to emphasize that data is obtained indirectly through the Event object, and event.data may have two data formats, one is String and the other is Blob. The handling of strings is needless to say, except for the handling of bloBs: call them back and forth with FileReader.

const reader = new FileReader();

// reader.readAsArrayBuffer(event.data);
reader.readAsText(event.data, 'utf8');
reader.onload = () = > {
  const message = reader.result;
  this.receiveMsg(message);
};
Copy the code

Send a message

// typeof data === 'string'
ws.send(data);
Copy the code

Shut down

ws.onclose = funtion(){
    // ...
}
Copy the code

Ws module

Set up service

The WebSocket here belongs to an object in the WS module.

let wss = new WebSocket.Server({ port:8080 });
Copy the code

Listening to the connection

Each time a new client establishes a connection, the server receives the message.

wss.on('connection'.async (ws, req) => {
    const { host } = req.headers;
})
Copy the code

Ws in the callback function is one-to-one for client communication, and REQ carries information in response to the TCP connection, such as host above is the host name of the connection party.

The heartbeat

For each WS connection, the heartbeat test can be performed by monitoring for a response at waitTime intervals. If no reply is received for a long time, the system disconnects to save resources.

setTimeout(() = > {
  if(! reply) { ws.close(); } }, waitTime);Copy the code

Ws Listening event

Note that ws.onMessage, etc., can bind only one callback function, while Ws.on (“message”,()=>{}) can bind multiple callback functions without overwriting.

There are two ways to receive a message, where the callback parameter message is of type String.

ws.onmessage = (message) = > {}
ws.on("message".(message) = > {})
Copy the code

Listening off:

ws.onclose = () = > {}
ws.on("close".() = > {})
Copy the code

Communication package

The problem with WebSocket is that we need to not only send and receive messages, but also type messages and transfer data similar to Http messages, so we can use serialization knowledge here.

encapsulation

In my project, I constructed the following structure:

{
    type: "init".// "message" or "close"
    data: {
        name: "xxx",
        avatar: "xxx",
        account: 100}}Copy the code

Type can define different message types. In data, the returned data is serialized by json.stringify () and deserialized by json.parse () after receiving the message.

encryption

RSA asymmetric encryption (generating public and private keys using OpenSSL) and the JsENCRYPT module are used to encrypt information during message transmission, for example, password transmission during initialization.

// const { JSEncrypt } = require('nodejs-encrypt');
const { JSEncrypt } = require('jsencrypt');

// Public key encryption
publicEncrypt(str) {
    const encrypt = new JSEncrypt();
    encrypt.setPublicKey(pubKey);
    return encrypt.encryptLong(str);
},

// Private key decryption
privateDecrypt(str) {
    const encrypt = new JSEncrypt();
    encrypt.setPrivateKey(privKey);
    return encrypt.decryptLong(str);
},
Copy the code

When encrypting with the above modules, you may encounter encryption failure because the string is too long, which you can do with the encryptLong module. In addition, another personal idea is to use MD5 encryption to shorten the string and then RSA encryption process.

The last

The content of this article is mainly WebSocket, narrating some of its basic use and some of the problems encountered in the process of doing projects.

Here I recommend my personal project, divided into Electron client and Nodejs server, including DSL parsing module (Tokenize,AST), log module, test module, etc. : MrPluto0/dslBot (github.com)

related

MrPluto0/dslBot interpreter (Human-computer Interaction)

Practice: Use JsENCRYPT with AXIOS to encrypt data asymmetrically – Nuggets (juejin. Cn)

Ruan Yifeng’s personal log :WebSocket

Ws Module (github.com)