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>

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

相关推荐
开开心心就好5 小时前
批量提取PDF中的图片,直接导出原图
前端·javascript·支持向量机·智能手机·pdf·html·启发式算法
比兔代理8 小时前
正向代理与反向代理技术辨析,为什么代理 IP 属于正向代理
服务器·网络·http·ip
默_笙9 小时前
🏛 给 AI 配一间办公室:Harness Engineering 六大模块与它的实现
前端·javascript
Ivanqhz10 小时前
SVD++算法
java·服务器·网络·深度学习·神经网络
linux_cfan11 小时前
videojs v10 源代码系列解读:14 · 谓词守卫:在运行时安全地调用能力
前端·javascript·音视频
迪康Defender12 小时前
终端安全实战:如何高效解决企业U盘泄密与管控难题
运维·网络·安全·web安全·终端安全管理
网安小学生(兼顾数据库版)13 小时前
固件+软件供应链:ONEKEY+Mend如何实现全链路安全覆盖
网络·安全·web安全
天若有情67313 小时前
【纯前端小工具】公历生日转农历,批量查询每年农历生日对应的公历日期(GitHub Pages在线直接用)
前端·javascript·github pages·农历转换·lunisolar·网页小工具
学习中的码虫13 小时前
网络编程5
服务器·网络
林语琛14 小时前
我写的 switch…break 被 Babel 偷偷吞了
前端·javascript·babel