<>业务场景
最近有一个业务场景是要做实时语音转义,考虑到实时性,所以决定采用websocket实现。
业务场景是A客户端(手机)进行语音转义的结果实时同步到B客户端(pc),这就需要用到websocket将A转义的结果发送给服务端,服务端接收到A的信息直接同步推送给B,所以它就和简单的无差别广播不同了。
看了网上的websocket示例,很少关于如何针对指定客户端推送消息的,解释的也是错误的。于是决定写一个大家拿去即用的示例。
<>websocket的通信过程
首先解释下面示例websocket服务的通信过程
1.服务端起一个websocket的端口服务
2.然后客户端去 new
WebSocket(服务端地址,如:ws://127.0.0.1:5201/?userId=liubao),此时就走到了服务端的wss.on(‘connection’)建立一个一对一连接了。为了方便大家理解,我把userId直接放url里了(真实业务场景一般是从header里拿token解析用户是谁)
3.服务端就把这个userId的请求连接池储存到clients数组里
4.此时客户端发送一个消息给服务端,就走到了 ws.on(‘message’)里,我们用data去接收客户端发送的消息
备注:从客户端接收到的数据是二进制的buffer信息(二进制信息是传统json信息速度的10倍+),所以在打印data时是个buffer,要想打印出来它的具体信息可以这样
console.log('%s',data);
取data信息时必须先转成字符串,否则是buffer数组信息,无法处理。
我们从客户端发送一个json信息包含userId和要发送的message
example:
// 客户端A { "userId": "liubao", "message": "给liubao一个小爱心" } // 客户端B { "userId":
"bob", "message": "给你bob一个大铁锤" }
5.有userId时遍历连接池,找到相同的userId连接池,进行推送消息
最后效果
<>服务端代码
copy下面代码到index.js文件,然后安装依赖和运行
npm i ws node index.js import { WebSocketServer } from 'ws'; const clients = []
; // 与客户端建立的连接池 const wss = new WebSocketServer({ port: 5201 }); //
创建一个websocket服务 wss.on('connection', function connection(ws, request, client) {
let url = request.headers.origin + request.url; //
example:ws://127.0.0.1:5201/?userId=liubao let userId = getParam(url, 'userId');
if (userId) { clients.push({ userId, ws: ws }); //
连接时只要url带userId参数,直接往客户端数组里塞入连接池信息 } ws.on('message', function message(data,
isBinary) { // 得到客户端往服务端发送的消息 try { let objMessage = JSON.parse(`${data}`); //
example:{ 'userId': 'liubao', 'message': '给你一个小爱心' } let { userId, message } =
objMessage; let count = 0; // 发送客户端数量 if (userId) { clients.forEach(e => { if (e
['userId'] === userId) { count++; e['ws'].send(`${message}`); } }); ws.send(`
已发送userId为${userId}的${count}个客户端`); } else { ws.send(JSON.stringify({ error:
'请发送指定userId的客户端' })); } } catch (err) { ws.send(JSON.stringify({ error: err.
message})); } }); ws.on('close', function close(event) { console.log('关闭了'); });
}); const getParam = (url, param) => new URLSearchParams(new URL(url).search).
get(param); // es6获取URL参数方法