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>

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

相关推荐
好_快31 分钟前
Lodash源码阅读-isNative
前端·javascript·源码阅读
IvanWKQ31 分钟前
本地服务重启-端口占用-显示和美国ip有个连接?存在恶意程序或是间谍程序?
linux·服务器·网络
听风吹等浪起33 分钟前
计算机网络基础:VLAN(虚拟局域网)
网络·计算机网络
nvvas36 分钟前
介绍高性能的HTTP和反向代理服务器Nginx
网络协议·nginx
好_快42 分钟前
Lodash源码阅读-reIsNative
前端·javascript·源码阅读
好_快1 小时前
Lodash源码阅读-baseIsNative
前端·javascript·源码阅读
好_快1 小时前
Lodash源码阅读-toSource
前端·javascript·源码阅读
忍者算法1 小时前
在 Linux 下,服务器如何知道某个 TCP 连接来了消息? 这就涉及 IO 事件通知机制!
websocket·网络协议·tcp/ip·http·信息与通信
aerror1 小时前
VsCode/Cursor workbench.desktop.main.js 的入口
javascript·ide·vscode
Oneforlove_twoforjob1 小时前
volta node npm yarn下载安装
前端·npm·node.js