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

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参数方法
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
要使用express-ws向指定客户端推送消息,你可以通过保存连接的方式来实现。以下是一个简单的示例代码: ```javascript const express = require('express'); const expressWs = require('express-ws'); const app = express(); const wsInstance = expressWs(app); // 创建一个存储连接的变量 const connections = []; // 处理WebSocket连接 app.ws('/ws', (ws, req) => { // 将新连接添加到连接列表中 connections.push(ws); // 监听消息事件 ws.on('message', (msg) => { console.log(`Received message: ${msg}`); }); // 监听关闭事件 ws.on('close', () => { // 从连接列表中移除关闭的连接 connections.splice(connections.indexOf(ws), 1); }); }); // 路由处理程序,用于向指定客户端发送消息 app.get('/send/:clientId', (req, res) => { const clientId = req.params.clientId; const message = req.query.message; // 在连接列表中查找指定客户端连接 const clientConnection = connections.find((ws) => ws.id === clientId); if (clientConnection) { // 向指定客户端发送消息 clientConnection.send(message); res.status(200).json({ success: true }); } else { res.status(404).json({ success: false, error: 'Client not found' }); } }); // 启动服务器 app.listen(3000, () => { console.log('Server started on port 3000'); }); ``` 在这个示例中,我们首先创建了一个用于保存连接的数组 `connections`。当有新的WebSocket连接建立时,我们将连接添加到数组中。当连接关闭时,我们将其从数组中移除。 然后,我们通过 `/send/:clientId` 路由处理程序来处理发送消息的请求。在这个处理程序中,我们首先从参数中获取目标客户端的ID和要发送的消息。然后,我们在连接列表中查找与目标客户端匹配的连接,并使用 `send` 方法向其发送消息。 请注意,这只是一个简单的示例,没有考虑到一些边界情况和错误处理。在实际应用中,你可能需要进行更多的错误检查和处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锅巴胸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值