websocket给指定客户端推送消息

业务场景

最近有一个业务场景是要做实时语音转义,考虑到实时性,所以决定采用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

扫描二维码关注公众号,回复: 15540637 查看本文章

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参数方法

猜你喜欢

转载自blog.csdn.net/sinat_15955423/article/details/127949531