Node.js + WebSocket 实现高性能实时聊天系统

Node.js + WebSocket 实现高性能实时聊天系统

在这里插入图片描述

一、前言

在现代 Web 应用中,实时通信 是聊天应用、在线协作、股票行情、直播弹幕等场景的关键需求。传统的 HTTP 轮询长轮询 存在高延迟、资源浪费等问题,而 WebSocket 允许 客户端与服务器建立持久连接,实现真正的双向实时通信

本篇文章将带你从零实现一个高性能 WebSocket 聊天系统,涵盖:
WebSocket 基本原理
Node.js 搭建 WebSocket 服务器
实现群聊、私聊功能
存储聊天记录(MongoDB)
在线用户管理(Redis)
前端 WebSocket 交互(Vue.js/React)

🚀 通过完整的代码示例,你将掌握 WebSocket 在 Node.js 生态中的最佳实践!


二、WebSocket 原理

2.1 WebSocket vs HTTP

协议连接方式适用场景
HTTP请求 - 响应,每次请求新建连接适用于普通网页加载
WebSocket连接建立后保持长连接,支持双向通信适用于聊天、推送、游戏等实时应用

2.2 WebSocket 连接流程

  1. 客户端发送 WebSocket 握手请求(Upgrade 请求)
  2. 服务器返回 101 状态码,升级连接
  3. 建立持久连接,支持双向通信
  4. 客户端或服务器主动关闭连接

三、Node.js 搭建 WebSocket 服务器

3.1 安装 WebSocket 依赖

npm init -y
npm install ws express cors mongoose redis

3.2 创建 WebSocket 服务器

const WebSocket = require("ws");
const express = require("express");

const app = express();
const server = require("http").createServer(app);
const wss = new WebSocket.Server({ server });

let clients = new Map(); // 存储在线用户

wss.on("connection", (ws, req) => {
    console.log("新用户连接");

    ws.on("message", (message) => {
        console.log("收到消息:", message);

        // 广播给所有用户
        clients.forEach(client => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(message);
            }
        });
    });

    ws.on("close", () => {
        console.log("用户断开连接");
    });
});

server.listen(3000, () => console.log("WebSocket 服务器运行在 ws://localhost:3000"));

效果

  • 服务器监听 WebSocket 连接
  • 任何用户发送消息,都会广播给其他所有在线用户

四、实现前端 WebSocket 交互

创建 index.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <title>WebSocket 聊天</title>
</head>
<body>
    <input id="message" placeholder="输入消息">
    <button onclick="sendMessage()">发送</button>
    <ul id="chat"></ul>

    <script>
        const ws = new WebSocket("ws://localhost:3000");

        ws.onopen = () => console.log("连接成功");
        ws.onmessage = (event) => {
            const li = document.createElement("li");
            li.textContent = event.data;
            document.getElementById("chat").appendChild(li);
        };

        function sendMessage() {
            const message = document.getElementById("message").value;
            ws.send(message);
        }
    </script>
</body>
</html>

效果

  • 连接 WebSocket 服务器
  • 用户输入消息后,所有人都能收到

五、支持私聊(私有消息)

5.1 修改 WebSocket 服务器

wss.on("connection", (ws) => {
    ws.on("message", (message) => {
        const data = JSON.parse(message);

        if (data.type === "private") {
            // 仅向特定用户发送消息
            const targetClient = clients.get(data.to);
            if (targetClient && targetClient.readyState === WebSocket.OPEN) {
                targetClient.send(JSON.stringify({ from: data.from, message: data.message }));
            }
        } else {
            // 群聊
            clients.forEach(client => {
                if (client !== ws && client.readyState === WebSocket.OPEN) {
                    client.send(message);
                }
            });
        }
    });
});

5.2 发送私聊消息

ws.send(JSON.stringify({ type: "private", to: "user2", from: "user1", message: "你好!" }));

效果

  • 支持私聊,仅目标用户收到消息

六、存储聊天记录(MongoDB)

6.1 安装 MongoDB 依赖

npm install mongoose

6.2 连接 MongoDB

const mongoose = require("mongoose");

mongoose.connect("mongodb://localhost:27017/chat", { useNewUrlParser: true, useUnifiedTopology: true });

const MessageSchema = new mongoose.Schema({
    sender: String,
    receiver: String,
    message: String,
    timestamp: { type: Date, default: Date.now }
});

const Message = mongoose.model("Message", MessageSchema);

6.3 存储聊天记录

ws.on("message", async (message) => {
    const data = JSON.parse(message);

    await Message.create({
        sender: data.from,
        receiver: data.to,
        message: data.message
    });

    // 发送消息
    ws.send(JSON.stringify({ message: data.message }));
});

效果

  • 自动存储聊天记录
  • 支持历史消息查询

七、在线用户管理(Redis)

const Redis = require("ioredis");
const redis = new Redis();

ws.on("message", async (message) => {
    const data = JSON.parse(message);

    if (data.type === "login") {
        await redis.sadd("online_users", data.username);
    } else if (data.type === "logout") {
        await redis.srem("online_users", data.username);
    }
});

效果

  • 用户上线/下线管理
  • 查询在线用户

八、安全优化

8.1 使用 JWT 认证

npm install jsonwebtoken
const jwt = require("jsonwebtoken");

const SECRET = "mysecret";

function verifyToken(token) {
    return jwt.verify(token, SECRET);
}

wss.on("connection", (ws, req) => {
    const token = req.url.split("?token=")[1];
    try {
        const user = verifyToken(token);
        ws.user = user;
    } catch {
        ws.close();
    }
});

效果

  • 所有连接必须通过 JWT 验证
  • 防止恶意连接

九、总结

功能实现方式
WebSocket 服务器ws.on("connection")
群聊clients.forEach(client.send())
私聊client.send(toUser)
MongoDB 存储mongoose.model("Message")
在线用户管理redis.sadd(username)
JWT 认证jsonwebtoken.verify(token)

本篇文章详细介绍了 WebSocket + Node.js 实现 实时聊天应用,包括 群聊、私聊、消息存储、在线用户管理、安全认证,希望对你的 WebSocket 开发有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

全栈探索者chen

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

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

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

打赏作者

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

抵扣说明:

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

余额充值