WebSocket认识
-
WebSocket
是一种全双工的通信协议,基于TCP协议,可以满足客户端和服务端双向通信需求。 -
默认端口也是80和443,握手阶段采用http协议,与http有良好的兼容性。
-
可以发送文本和二进制数据。
-
无同源限制,客户端可以与任意服务器建立通信。
WebSocket属性与方法
// 利用 `WebSocket` 构造函数可以创建 指定url的 WebSocket 连接。
const ws = new WebSocket('ws://ip:port/api_path');
// ws.url WebSocket 的绝对路径 - 只读
// ws.readyState 当前的链接状态 - 只读
// [0-CONNECTING: 链接中 | 1-OPEN: 成功链接可以通讯 | 2-CLOSING: 正在关闭 | 3-CLOSED: 已关闭或没有链接成功]
// ws.protocol 服务器选择的下属协议 - 只读
// [创建 WebSocket 对象时,参数protocols中指定的字符串,当没有已建立的链接时为空串。]
// ws.extensions 服务器选择的扩展 - 只读
// [目前链接可以协定的扩展值只有空字符串或者一个扩展列表]
// ws.bufferedAmount 未发送至服务器的字节数 - 只读
// [已经被send()方法放入队列中但还没有被发送到网络中的数据的字节数。一旦队列中的所有数据被发送至网络,则该属性值将被重置为0。但是,若在发送过程中连接被关闭,则属性值不会重置为0。如果你不断地调用send(),则该属性值会持续增长]
// ws.binaryType 使用二进制的数据类型连接 [blob | arraybuffer]
// 事件监听 - 实例方法
ws.onopen = (event) => {
// 当一个 WebSocket 连接成功时触发
}
ws.onmessage = (event) => {
// 当通过 WebSocket 收到数据时触发
};
ws.onerror = (event) => {
// 当一个 WebSocket 连接因错误而关闭时触发,例如无法发送数据时
}
ws.onclose = (event) => {
// 当一个 WebSocket 连接被关闭时触发
}
// 事件监听 - 添加监听
ws.addEventListener('open', (event) => { });
ws.addEventListener('message', (event) => { });
ws.addEventListener('error', (event) => { });
ws.addEventListener('close', (event) => { });
// 主动向服务端发送消息
ws.send('hello server')
// 主动关闭 WebSocket 连接
ws.close('1005', '通信完毕');
WS的一个简单例子
现在有一个 machine 的列表,可以对 machine 进行启动和停止操作。其中有一些状态需要实时获取
client端
const setWs = (callback) => {
const ws = new WebSocket(`ws://${location.host}/api/machine/status`);
ws.onopen = (event) => {
// 建立链接成功后可以进行一些处理
console.log('onopen = ', event);
// 主动给服务器发送消息
ws.send('from client', () => {
console.log('success');
})
}
ws.onclose = (event) => {
// 链接关闭 - 进行一些处理
console.log('onclose = ', event);
}
ws.onerror = (event) => {
// ws链接异常处理
console.log('onerror = ', event);
}
ws.onmessage = (event) => {
// 正常接受到消息进行处理
console.log('onmessage = ', event);
if(callback) {
callback(event.data);
}
};
}
const getMachineData = () => {
$.ajax({
url: '/machine/info?id=1',
dataType: 'json',
success: (res) => {
console.log('res', res);
$('#name').text(res?.data?.name??'');
$('#status').text(res?.data?.status??'');
}
})
}
// 初始获取machine数据
getMachineData();
// 建立ws链接
const ws = setWs(status => {
$('#status').text(status);
});
// 启动操作
const onRun = () => {
$.ajax({
url: '/machine/run?id=1',
dataType: 'json',
success: (res) => {
console.log('res', res);
$('#status').text(res?.data??'');
}
})
}
// 停止操作
const onStop = () => {
$.ajax({
url: '/machine/stop?id=1',
dataType: 'json',
success: (res) => {
console.log('res', res);
$('#status').text(res?.data??'');
}
})
}
server端
const express = require('express');
const { createServer } = require('http');
const path = require('path');
const { WebSocketServer } = require('ws');
const machineRoute = require('./routes/machine');
const machineService = require('./service/machine');
const utils = require('./utils');
// 设备数据初始化
machineService.init();
const app = express();
// 配置静态文件目录
app.use(express.static(path.join(__dirname, '/static')));
// 加载路由器
machineRoute(app, 'machine');
// 利用现成的server创建 ws 服务
const server = createServer(app);
const wss = new WebSocketServer({ server, path: '/api/machine/status' });
// ws 链接监听
wss.on('connection', (ws) => {
console.log('wss-connection');
const aListener = (status) => {
// 设备启动/停止成功后的监听器-给client发送状态
ws.send(status);
}
// 添加监听器
utils.addListen(aListener);
ws.on('message', function message(data) {
console.log('message', data);
});
ws.on('close', () => {
console.log('wss-closed');
// 移除监听器
utils.removeListen(aListener);
})
});
// 服务启动监听
server.listen(8080, () => {
console.log('server is running on 8080');
})
demo效果