【JSAPI】WebSocket
2021/11/15 14:25:33
介绍
http 协议通信只能由客户端发起,这意味着服务器无法主动推送消息给客户端,以往对于这种需求是通过客户端轮询请求来解决的。
轮询请求就像是大水漫灌,会造成资源浪费,服务器数据未更新之前所有的请求都是无效请求。
在这种情况下,websocket 应运而生,它最大的特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
特点
建立在 TCP 协议之上,服务器端的实现比较容易。
与 HTTP 协议有着良好的兼容性。默认端口也是 80 和 443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
数据格式比较轻量,性能开销小,通信高效。
可以发送文本,也可以发送二进制数据。
没有同源限制,客户端可以与任意服务器通信。
协议标识符是 ws(如果加密,则为 wss),服务器网址就是 URL。
应用
client 客户端
- WebsocketBaseService.js
封装 websocket
let socket = null;
let maxReconnectionTime = 10;
let reconnectionTime = 0;
let reconnectionTimmer = null;
let messageListener = () => {};
export function initWebsocket(options) {
if (!options.url) {
console.log("ws地址有误");
return;
}
function reconnection() {
if (reconnectionTime < maxReconnectionTime) {
reconnectionTimmer = setTimeout(() => {
reconnectionTime++;
createWebsocket();
}, 3000);
}
}
function createWebsocket() {
socket = new WebSocket(options.url);
if (typeof options.messageHandler === "function") {
messageListener = options.messageHandler;
}
// Connection opened
socket.addEventListener("open", function () {
console.log("websocket连接成功", options.url);
clearTimeout(reconnectionTimmer);
reconnectionTime = 0;
});
socket.addEventListener("message", function (event) {
messageListener(JSON.parse(event.data));
});
socket.addEventListener("error", function (event) {
// console.log("Message from server ", event.data);
console.log("error", event);
});
socket.addEventListener("close", function (event) {
console.log("close", event);
reconnection();
});
}
createWebsocket();
}
export function sendData(data) {
socket.send(data);
}
- index.js
在需要的地方应用,传入 url
和 messageHandler
import { initWebsocket } from "./WebsocketBaseService";
initWebsocket({
url: "ws://localhost:3001",
messageHandler(event) {
// todo...
},
});
server 服务端
在 node 中使用 nodejs-websocket
搭建 websocket 服务
安装 nodejs-websocket
,文档位置:https://www.npmjs.com/package/nodejs-websocket
npm i nodejs-websocket
- WebsocketService.js
封装 websocket 服务
let ws = require("nodejs-websocket");
let port = 3000;
let server;
let websocketUrl = "ws://localhost:";
let serverConnection = false;
exports.initWebsocket = function () {
return new Promise((resolve) => {
function websocketConnection() {
websocketUrl += port;
serverConnection = true;
resolve(websocketUrl);
}
function reconstruction() {
port++;
createServer();
}
function createServer() {
server = ws
.createServer(function (conn) {
console.log("New connection", server.connections.length);
conn.on("text", function (str) {
console.log("Received " + str);
conn.sendText(str.toUpperCase() + "!!!");
});
conn.on("close", function (code, reason) {
console.log("Connection closed");
});
conn.on("error", function (code, reason) {
console.log("Connection error");
});
})
.listen(port, "", websocketConnection);
server.on("error", reconstruction);
}
createServer();
});
};
function broadcast(server, msg) {
// 给所有客户端发送消息
server.connections.forEach(function (conn) {
conn.sendText(msg);
});
}
exports.sendData = function (data) {
broadcast(server, JSON.stringify(data));
};
- index.js
启动 ws 服务
let { initWebsocket } = require("../service/WebsocketService");
initWebsocket().then((wsUrl) => {
console.log(`ws running at: ${wsUrl}`);
});