You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让WebSocket实现实时通信?Express集成问题排查

问题描述

我在后端用Express集成WebSocket,前端用浏览器原生WebSocket API,目前能实现客户端和服务器互发消息,但所有操作必须刷新页面才触发。WebSocket应该支持实时通信:比如修改服务器文件里的消息内容后,要立刻在浏览器控制台显示变更;修改客户端脚本的消息内容后,要立刻在服务器控制台显示变更(我已经用nodemon跑服务器,代码变更应该快速生效)。但现在必须刷新页面发起请求,服务器才会升级连接并返回消息,请问我在代码或概念上有遗漏吗?


后端代码(app.js)

const express = require('express')
const app = express()
const path = require('path')
const WebSocketServer = require('websocket').server; 

app.set('view engine', 'html');
app.use(express.static(path.join(__dirname, '/public')))

const port = 8080

app.get('/', (req, res) => {
  res.render('index')
})

const server = app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

wsServer = new WebSocketServer({
    httpServer: server
});

function originIsAllowed(origin) {
  return true;
}

wsServer.on('request', function(request) {
    if (!originIsAllowed(request.origin)) {
      request.reject();
      console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
      return;
    }
    
    var connection = request.accept(null, request.origin);
    console.log((new Date()) + ' Connection accepted.');
    
    connection.on('message', function(message) {
        if (message.type === 'utf8') {
            console.log('Received Message: ' + message.utf8Data);
            connection.sendUTF("server says hi");
        }
        else if (message.type === 'binary') {
            console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
            connection.sendBytes(message.binaryData);
        }
    });
    
    connection.on('close', function(reasonCode, description) {
        console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
    });
});

前端代码(client.js)

const socket = new WebSocket('ws://localhost:8080');

// Connection opened
socket.addEventListener('open', function (event) {
    socket.send('Hello to Server!');
});

// Listen for messages
socket.addEventListener('message', function (event) {
    console.log('Message from server ', event.data);
});

问题分析与解决

核心问题拆解

你的代码能建立WebSocket连接并收发消息,但实时性需求没落地,本质是两个关键缺失:

  1. 服务器没有主动推送能力,无法在代码变更后给已连接客户端发消息
  2. 客户端没有自动重连机制,代码变更或服务器重启后无法自动恢复连接

具体解决步骤

1. 服务器端:维护连接池,实现主动推送

现在服务器只在收到客户端消息时被动回复,需要新增连接存储逻辑,支持主动向所有在线客户端推送消息:

// 新增:存储所有活跃的WebSocket连接
const activeConnections = [];

wsServer.on('request', function(request) {
    // ... 保留原有的origin检查、连接接受逻辑 ...
    
    var connection = request.accept(null, request.origin);
    console.log((new Date()) + ' Connection accepted.');
    // 新增:将新连接加入连接池
    activeConnections.push(connection);
    
    connection.on('message', function(message) {
        // ... 保留原有的消息处理逻辑 ...
    });
    
    connection.on('close', function(reasonCode, description) {
        console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
        // 新增:连接断开时从连接池移除
        const index = activeConnections.indexOf(connection);
        if (index !== -1) {
            activeConnections.splice(index, 1);
        }
    });
});

// 新增:主动广播消息的函数,修改服务器消息后直接调用即可
function broadcastToAllClients(message) {
    activeConnections.forEach(conn => {
        if (conn.connected) {
            conn.sendUTF(message);
        }
    });
}

// 示例:比如你修改了服务器回复内容,调用这个函数就能立刻推送给所有客户端
// broadcastToAllClients("新的服务器回复内容");

2. 客户端:添加自动重连,适配服务器重启/代码变更

客户端代码变更后浏览器不会自动刷新,服务器重启会断开现有连接,需要给客户端加自动重连逻辑:

let socket;

function initWebSocket() {
    socket = new WebSocket('ws://localhost:8080');
    
    socket.addEventListener('open', function (event) {
        console.log('WebSocket连接成功');
        socket.send('Hello to Server!');
    });
    
    socket.addEventListener('message', function (event) {
        console.log('Message from server ', event.data);
    });
    
    // 新增:连接断开后自动重试
    socket.addEventListener('close', function() {
        console.log('连接断开,3秒后尝试重连');
        setTimeout(initWebSocket, 3000);
    });
    
    // 新增:连接错误处理
    socket.addEventListener('error', function(err) {
        console.error('WebSocket连接出错:', err);
    });
}

// 初始化连接
initWebSocket();

如果想让客户端代码变更后自动刷新页面,可以用Vite、Webpack Dev Server这类带热重载的工具,修改代码后浏览器会自动刷新并重建WebSocket连接。

3. 概念澄清

WebSocket的"实时通信"指连接建立后,双方可随时主动收发消息,而非"代码变更自动同步"。代码变更的实时生效需要额外处理:

  • 服务器端:通过连接池主动推送变更内容
  • 客户端:通过自动重连或热重载,发送新的消息内容

内容的提问来源于stack exchange,提问作者Deke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:36:07