nodejs使用WebSocket实现聊天效果

在nodejs中使用WebSocket实现聊天效果(简易实现)

安装

bash 复制代码
npm i ws

实现

创建 server.js

javascript 复制代码
/**
 * 创建一个 WebSocket 服务器,监听指定端口,并处理客户端连接和消息。
 *
 * @param {Object} WebSocket - 引入的 WebSocket 模块,用于创建 WebSocket 服务器。
 *
 * 功能步骤:
 * 1. 创建一个 WebSocket 服务器,监听端口 1024。
 * 2. 维护一个消息列表 `list`,用于存储客户端发送的消息。
 * 3. 当客户端发送消息时,解析消息内容并将其添加到消息列表中。
 * 4. 将更新后的消息列表发送回客户端。
 */

const WebSocket = require('ws')

// 消息列表,用于存储所有客户端发送的消息
let list = []

// 创建 WebSocket 服务器,监听端口 1024
const wss = new WebSocket.Server(
  {
    port: 1024
  },
  () => {
    console.log('Server is listening on port 1024')
  }
)

// 监听客户端连接事件
wss.on('connection', function (ws) {
  // 监听客户端发送的消息事件
  ws.on('message', function (msg) {
    // console.log('收到客户端消息', JSON.parse(msg))
    try {
      // 解析客户端发送的消息
      if (msg) {
        // 如果消息没有错误,将消息内容添加到消息列表中
        list.push(JSON.parse(msg).netName + ' 说: ' + JSON.parse(msg).msg)
      }
    } catch (error) {}
    // 将更新后的消息列表发送回客户端
    ws.send(JSON.stringify(list))
  })
})

创建 client.js 测试

javascript 复制代码
/**
 * 创建一个WebSocket客户端,用于连接指定的WebSocket服务器。
 *
 * 参数:
 * - 'ws://192.168.8.183:1024': WebSocket服务器的URL地址。
 */
const WebSocket = require('ws')

const ws = new WebSocket('ws://192.168.8.183:1024')

// 当WebSocket连接成功打开时触发
ws.on('open', function () {
  console.log('Client is listening on port 1024') // 打印日志,表示客户端已成功连接到服务器
  ws.send(JSON.stringify('Hello World')) // 向服务器发送消息
})

// 当接收到服务器发送的消息时触发
ws.on('message', function (msg) {
  console.log('收到服务器消息', JSON.parse(msg))
  // ws.send(msg) // 将接收到的消息原样返回给服务器
})

// 当WebSocket连接关闭时触发
ws.on('close', function () {
  console.log('Client close') // 打印日志,表示客户端连接已关闭
})

分别运行以上两个文件,如果互相能收到消息表示服务运行正常
创建 index.html 文件

html 复制代码
<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>WebSocket 消息发送</title>
    <style>
      /* 消息输入框样式 */
      #text {
        width: 350px;
        height: 30px;
      }
      /* 用户名输入框样式 */
      #netName {
        width: 150px;
        height: 30px;
      }
    </style>
  </head>

  <body>
    <!-- 消息显示区域 -->
    <textarea id="msg" cols="80" rows="30" readonly></textarea><br />
    <!-- 用户名输入框 -->
    <input id="netName" type="text" placeholder="名称" />
    <!-- 消息输入框 -->
    <input id="text" type="text" placeholder="消息" />
    <!-- 发送按钮 -->
    <button id="sendButton">发送</button>

    <script>
      let ws = null // WebSocket 连接对象

      /**
       * 初始化 WebSocket 连接
       */
      function initWebSocket() {
        if (ws) return // 避免重复连接

        ws = new WebSocket('ws://192.168.8.183:1024')

        ws.onopen = () => {
          console.log('WebSocket 连接已建立')
        }

        ws.onmessage = (evt) => {
          try {
            const receivedData = JSON.parse(evt.data)
            msg.value = Array.isArray(receivedData) ? receivedData.join('\n') : JSON.stringify(receivedData, null, 2)
          } catch (error) {
            console.error('解析接收到的数据失败:', error)
          }
        }

        ws.onerror = (error) => {
          console.error('WebSocket 错误:', error)
        }

        ws.onclose = () => {
          console.log('WebSocket 连接已关闭,尝试重新连接...')
          ws = null
          setTimeout(initWebSocket, 5000) // 5 秒后重连
        }

        setInterval(() => {
          ws.send('')
        }, 1000)
      }

      /**
       * 发送消息到 WebSocket 服务器
       * @param {Object} data - 要发送的数据对象
       */
      function sendMessage(data) {
        if (!ws || ws.readyState !== WebSocket.OPEN) {
          console.warn('WebSocket 未打开,尝试重新连接...')
          initWebSocket()
          return
        }

        if (!data) {
          data = { err: 1 }
        } else if (typeof data !== 'object' || Array.isArray(data)) {
          console.error('数据格式无效')
          return
        }

        ws.send(JSON.stringify(data))
      }

      /**
       * 处理发送按钮点击或回车键事件
       */
      function handleSend() {
        const netNameValue = netName.value.trim()
        const textValue = text.value.trim()

        if (!netNameValue || !textValue) {
          alert('用户名和消息不能为空')
          return
        }

        const message = {
          netName: netNameValue,
          msg: textValue
        }

        sendMessage(message)
        text.value = '' // 清空消息输入框
      }

      // 初始化 WebSocket 连接
      initWebSocket()

      // 绑定发送按钮点击事件
      document.getElementById('sendButton').addEventListener('click', handleSend)

      // 监听回车键事件
      document.addEventListener('keyup', (e) => {
        if (e.key === 'Enter') {
          handleSend()
        }
      })
    </script>
  </body>
</html>

用两个浏览器打开此文件,就可以互相发送消息

相关推荐
Yana.nice4 分钟前
nsswitch.conf配置文件内容解析
运维·服务器·网络
前端康师傅4 分钟前
JavaScript 变量详解
前端·javascript
Sun_light5 分钟前
队列:先进先出的线性数据结构及其应用
前端·javascript·算法
zh_1999511 分钟前
计算机网络面试汇总(完整版)
网络·tcp/ip·php
萌萌哒草头将军19 分钟前
⚓️ Oxlint 1.0 版本发布,比 ESLint 快50 到 100 倍!🚀🚀🚀
前端·javascript·vue.js
Yana.nice35 分钟前
sysctl优先级顺序
服务器·前端·网络
karshey1 小时前
【Element Plus】Menu组件:url访问页面时高亮对应菜单栏
前端·javascript·vue.js
Mintopia1 小时前
Three.js 自定义几何体:解锁 3D 世界的创造力
前端·javascript·three.js
Mintopia1 小时前
计算机图形学碰撞检测:数字世界的 “防碰瓷” 秘籍
前端·javascript·计算机图形学