• WebSocket在node端和客户端的使用


    摘要

    如果想要实现一个聊天的功能,就会想到使用WebSocket来搭建。那如果没有WebSocet的时候,我们会以什么样的思路来实现聊天功能呢?

    假如有一个A页面 和 B页面进行通信,当A发送信息后,我们可以将信息存储在文件或者数据库里。
    但是B页面并不知道A发送了信息,所以如果想要让B 页面实时的去展示A发送的信息,我们只能在B页面设置一个定时器,在定时器中一直去查询文件或者数据库的信息,如果有新的消息,那么就在B页面进行展示,同理,在A页面也要以相同的方法去实现。

    在这里插入图片描述

    对于这个方法,需要不停的去轮训,耗费了大量的空间和时间,那如果在A 发送消息后,B页面可以主动的接收到对应的消息,就不需要在定时器中去不停的查找了。

    WebSocket,就是为了解决这个问题出现的。WebSocket支持双向通信,服务器和客户端之间可以随时互相发送信息,实时性更强。

    1. ws模块

    在node中,大家对于fs模块,http模块应该已经不陌生了。这里我们需要引入的模块是ws模块,需要通过npm install进行安装。

    WS模块是一个WebSocket协议的实现,它允许客户端(一般是浏览器)和服务器之间建立持久连接,进行实时双向通信。这种持久连接可以使得数据传输更加高效,适用于需要实时交互的应用场景,如在线聊天室、游戏等。

    现在我们简单的使用一下:
    新建一个文件夹,npm init初始化,再npm install ws
    在文件夹下新建一个index.js

    const WebSocket = require('ws')
    
    const wss = new WebSocket.Server({port: 3004});
    
    wss.on('connection', (ws) => {
      //如果有客户端连接,就会进入这个回调
      console.log('Client connected');
      ws.on('message', (message) => {
        // 如果有客户端发送消息,就会进入这个回调
        console.log(message.toString());
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这样一个简单的ws的node端就实现了。现在我们新建一个html文件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <div style="width: 200px;height:300px;background: #e2e2e2;margin-bottom: 20px;">
        <span></span>
      </div>
      <input type="text">
      <button>发送</button>
    
      <script>
      	// 创建ws模块
        var ws = new WebSocket(`ws://localhost:3004`);
        // 建立连接
        ws.onopen = function () {
          // 客户端向服务端发送消息
          ws.send('hello word');
          console.log('已连接');
        }
      </script>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    这样就是一个简单的客户端向服务端发送消息的模型。

    2.从服务端发往客户端

    上面的代码主要实现了从客户端到服务端,但这也是正常思路。我们肯定是希望从服务端到客户端。
    所以我们要在服务端接受到消息后,也往客户端发送消息:

    const WebSocket = require('ws')
    
    const wss = new WebSocket.Server({port: 3004});
    
    wss.on('connection', (ws) => {
      console.log('Client connected');
      ws.on('message', (message) => {
        console.log(message.toString());
        // 服务端向客户端发送消息
        ws.send('hello word too')
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在客户端里,我们通过onmessage的回调来进行接受:

      <script>
        var ws = new WebSocket(`ws://localhost:3004`);
        ws.onopen = function () {
          ws.send('hello word');
          console.log('已连接');
        }
        ws.onmessage = async function(mes) {
          // 接受服务端发送的消息
          console.log(mes.data)
        }
      </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3.对于不同的客户端,返回不同的信息

    那如果想实现出一个聊天的功能,服务端接受到A的消息,要给B发送消息。
    上面的代码似乎只能,谁给服务端发,服务端就给谁返回。

    所以在node的代码里,我们需要每次建立连接的时候,将对应的ws保存起来,然后根据客户端的信息,用指定的ws去返回信息。

    现在我们如果有两个html,每个html在初始化页面的时候,给服务端发送一个消息,代表自己已经连接的信息。
    点击按钮的时候,给服务端发送的信息,要携带希望传递的客户端的信息。

    页面1:

      <script>
        var ws = new WebSocket(`ws://localhost:3004`);
        ws.onopen = function () {
          ws.send(JSON.stringify({name: 'zhangsan', message: 'init'}));
          console.log('已连接');
        }
        ws.onmessage = async function(mes) {
          console.log(mes.data)
        }
        
        function click() {
          const value = input.value;
          ws.send(JSON.stringify({name: 'lisi', message: '你好lisi'}))
        }
      </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    页面2:

      <script>
        var ws = new WebSocket(`ws://localhost:3004`);
        ws.onopen = function () {
          ws.send(JSON.stringify{name: 'lisi', message: 'init'}));
          console.log('已连接');
        }
        ws.onmessage = async function(mes) {
          console.log(mes.data)
        }
        
        function click() {
          const value = input.value;
          ws.send(JSON.stringify({name: 'zhangsan', message: '你好zhangsan'}))
        }
      </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在node端中,我们要根据message是否为init,进行判断。

    const WebSocket = require('ws')
    
    const wss = new WebSocket.Server({port: 3004});
    const wsList = {}
    
    wss.on('connection', (ws) => {
      ws.on('message', (message) => {
        const result = JSON.parse(message);
        // 页面初始化的时候,使用wsList将ws进行缓存
        if(result.message === 'init') {
          wsList[result.name] = ws;
        }else {
          // 根据name的值来给指定的客户端发送信息
          const ws = wsList[result.name];
          ws.send(result.message)
        }
      })
    
      ws.on('close', () => {
        Object.keys(wsList).forEach(item => {
          // 当websoket关闭的时候,要清空对应的ws
          if(wsList[item].readyState !== 1) {
            delete wsList[item]
          }
        })
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    以上就是对应ws模块,和WebSocket的简单阐述。

  • 相关阅读:
    秋招过半零Offer怎么办?
    51单片机3【单片机的种类】
    INTERSPEECH 2022 | 钉钉蜂鸣鸟音频实验室论文入选国际顶会,创新提出窄带滤波网络架构
    编译OpenWrt内核驱动
    自主式模块化无人机设计
    Hadoop MapReduce 1.x 工作原理
    大型医院HIS系统源码 优质源码 医院管理系统源码
    【校招VIP】前端算法考察之链表算法
    优思学院|六西格玛绿带和黑带的年薪收入有多少?
    基于lstm DNN的多变量单变量时间预测项目-完整数据+代码
  • 原文地址:https://blog.csdn.net/weixin_46726346/article/details/134306696