The front-end code
class Socket { constructor({ url = '', token = '', roomId = '', callback = () => {} }) { this.url = url; this.callback = callback; this.token = token; this.roomId = roomId; this.ws = {}; this.init(); } init() { this.ws = new WebSocket(`wss://${this.url}`); This.ws. Onopen = () => this.onOpen(this.token, this.roomId); This.ws. Onmessage = e => this.onMessage(e, this.callback); This.ws. Onerror = this.onError; // This.ws. Onclose = this.onclose; } onOpen(token, roomId) {this.send({event: 'auth', message: {token, roomId}}); } send(data) { this.ws.send(JSON.stringify(data)); } onMessage(e, callback) { const data = JSON.parse(e.data); Switch (data.event) {case 'noAuth': // Failed to verify, return the login page location.href = '/login'; break; This. send({event: 'heartbeat', message: 'pong'}); clearTimeout(this.pingTimeout); this.pingTimeout = setTimeout(() => { this.close(); this.onError(); }, 30000 + 1000); break; default: callback(data); }} onError() {console.log('websocket connection error '); SetTimeout (() => {this.init(); }, 1000); } onClose() {console.log('websocket connection is down '); } close() {// Close the webSocket connection. Disable the heartbeat detection timer to prevent the original timer from running after the connection is disconnected clearTimeout(this.pingtimeout); this.ws.close(); }}Copy the code
The back-end code
import WebSocket from "ws"; import fs from "fs"; import https from "https"; import jwt from "jsonwebtoken"; class Socket { constructor(config) { this.config = { port: 8080, ... config, }; this.wss = {}; this.init(); } init() { const server = https.createServer({ cert: fs.readFileSync( __dirname + "/httpsConfig/5163307_www.pengjianming.top.pem" ), key: fs.readFileSync( __dirname + "/httpsConfig/5163307_www.pengjianming.top.key" ), }); This. WSS = new websocket. Server({Server}); This.wss. on("connection", (ws) => {// The connection is successful and the heartbeat detection is enabled. this.heartbeat(ws); ws.on("message", (msg) => this.message(ws, msg)); ws.on("close", () => this.close(ws, this.wss)); }); server.listen(8080); } message(ws, msg) { const data = JSON.parse(msg); Const event = {// After the authentication, add the authentication information and add the corresponding user information to the ws auth: (params) => { const auth = jwt.verify(params.token, "shared-secret"); if (auth) { ws.user = auth; ws.roomId = params.roomId; } else { ws.send( JSON.stringify({ event: "noAuth", }) ); {ws.isalive: () => {ws.isalive = true; }}; event[data.event](data.message); } send(user_name, message) {// Send a message to a client based on the user name [...this.wss.clients]. Filter ((client) =>! client.roomId) .forEach((client) => { if ( client.readyState === WebSocket.OPEN && client.user.user_name === user_name ) { client.send(JSON.stringify({ event: "tip", message })); }}); } broadcast(roomId, [...this.wss.clients].filter((client) => client.roomId).foreach ((client) => {if (user_id); client.readyState === WebSocket.OPEN && client.roomId === roomId && user_id ! == client.user.id ) { client.send(JSON.stringify({ event: "chat" })); }}); } close(ws) {// Close the connection to close the corresponding timer clearInterval(ws-interval); Websocket ws.interval = setInterval(() => {if (ws.isalive === =) false) return ws.terminate(); ws.isAlive = false; ws.send( JSON.stringify({ event: "heartbeat", message: "ping", }) ); }, 30000); } } export default new Socket();Copy the code
The process that
Initialize the
When the object is created, init method is called to create the webSocket instance and the connection is successful. At this time, onOpen will also be called to verify the identity with the back end and create the connection information. According to the token passed, the identity can be determined and the single point of information can be sent If the identity verification passes, the corresponding connection information is set. If the identity verification fails, the noAuth event of event will be sent to inform the client that the identity verification fails. After receiving the noAuth event, the client will switch back to the login page for re-login
The heartbeat detection
Create a WebSocket instance. If the connection succeeds, the backend will start heartbeat detection. If the connection succeeds, isAlive = will be set first If the client does not send the heartbeat back within the specified time, set isAlive =. If the client does not send the heartbeat back within the specified time, set isAlive = True, so, at the beginning of the second heartbeat detection, will think that the client disconnected died directly, if the client returns corresponding to the heartbeat, the heartbeat is normal, every time the client receives a heartbeat, all would the clearance before the timer, open up a new timer, if within the prescribed time, the server didn’t detect heartbeat again, will be closed This client, reconnect
Agreement that
If HTTP is used, the protocol is WS, if HTTPS is used, the protocol is WSS, and the certificate file needs to be set
Broadcast information
Iterate over all connected clients, filter by the roomId passed when they connect, and then send the information
Single point sending information
Passes through all connected clients, based on previously authenticated information
Pass the message
The message needs to be converted to a character, not converted to get the message type
How to use
this.socket = new Socket({ url: 'www.pengjianming.top:8080', token: getToken(), roomId: this.$route.query.id, callback: data => { if (data.event === 'chat') { this.getTicket(); }}});Copy the code
After creation, every time the server returns a message, callback will be called if the event is not the specified heartbeat and noauth, where the desired event notification can be made