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

无法与Node.js服务器建立WebSocket连接,请求排查问题

问题描述

尝试搭建极简WebSocket服务器,但浏览器无法建立连接,加载HTML页面时出现错误:

error:index.html:9 WebSocket connection to 'ws://localhost:8080/?chatId=15432' failed:

服务器代码

const http = require("http");
const WebSocketServer = require("websocket").server;
const server = http.createServer((req, res) => {});
const websocket = new WebSocketServer({
  httpServer: server,
  autoAcceptConnections: false,
});

const chats = new Map();

websocket.on("request", (request) => {
  let connection = request.accept(null, request.origin);
  console.log(connection);
  console.log(new Date() + " Connection accepted.");
  let chatId = request.resourceURL.query.chatId;

  if (!chats.has(chatId)) {
    chats.set(chatId, []);
  }

  chats.get(chatId).push(connection);

  connection.on("message", (message) => {
    console.log("Received Message: " + message.utf8Data);
    let chatConnections = chats.get(chatId);
    chatConnections.forEach((chatConnection) => {
      if (chatConnection !== connection) {
        chatConnection.sendUTF(message.utf8Data);
        console.log(connection);
      }
    });
  });
  connection.on("close", (reasonCode, description) => {
    console.log(
      new Date() + " Peer " + connection.remoteAddress + " disconnected."
    );
    let chatConnections = chats.get(chatId);
    chatConnections.splice(chatConnections.indexOf(connection), 1);
    if (chatConnections.length === 0) {
      chats.delete(chatId);
    }
  });
});
server.listen(8080, "localhost", () => {
  console.log("listening on port 8080");
});

客户端代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script>
      let webSocket = new WebSocket("ws://localhost:8080?chatId=15432", null);
      webSocket.onopen = (event) => {
        webSocket.send("Hey guys, here's my first message");
        console.log("Connection Opened Client");
      };

      webSocket.onclose = function () {
        console.log("WebSocket connection closed.");
      };
    </script>
  </head>
  <body></body>
</html>

预期能成功建立连接并接收客户端消息,但功能未实现,请问是否遗漏关键步骤?


问题分析与解决

你的代码存在两个核心问题导致连接失败:

  1. Origin验证缺失
    当autoAcceptConnections设为false时,服务器必须显式验证请求的Origin是否合法,否则浏览器会因为跨域安全策略拒绝连接。你的代码直接调用request.accept但未做任何Origin校验,这是连接失败的主要原因。

  2. 子协议处理冗余
    客户端创建WebSocket时传入null作为子协议参数,虽然服务器对应传入null能匹配,但更简洁的方式是两端都不指定子协议,避免不必要的协商干扰。

修改后的服务器代码

const http = require("http");
const WebSocketServer = require("websocket").server;
const server = http.createServer((req, res) => {});
const websocket = new WebSocketServer({
  httpServer: server,
  autoAcceptConnections: false,
});

// 允许的Origin列表,根据实际运行环境调整
const allowedOrigins = ["http://localhost", "http://127.0.0.1", "null"];

const chats = new Map();

websocket.on("request", (request) => {
  // 验证请求Origin是否在允许列表内
  const origin = request.origin;
  if (!allowedOrigins.includes(origin)) {
    request.reject(403, "Origin not allowed");
    console.log(new Date() + " Connection rejected: Origin " + origin + " not allowed");
    return;
  }

  // 接受连接,不指定子协议
  let connection = request.accept(null, origin);
  console.log(connection);
  console.log(new Date() + " Connection accepted.");
  let chatId = request.resourceURL.query.chatId;

  if (!chats.has(chatId)) {
    chats.set(chatId, []);
  }

  chats.get(chatId).push(connection);

  connection.on("message", (message) => {
    console.log("Received Message: " + message.utf8Data);
    let chatConnections = chats.get(chatId);
    chatConnections.forEach((chatConnection) => {
      if (chatConnection !== connection) {
        chatConnection.sendUTF(message.utf8Data);
      }
    });
  });
  connection.on("close", (reasonCode, description) => {
    console.log(
      new Date() + " Peer " + connection.remoteAddress + " disconnected."
    );
    let chatConnections = chats.get(chatId);
    if (chatConnections) {
      const index = chatConnections.indexOf(connection);
      if (index !== -1) {
        chatConnections.splice(index, 1);
        if (chatConnections.length === 0) {
          chats.delete(chatId);
        }
      }
    }
  });
});
server.listen(8080, "localhost", () => {
  console.log("listening on port 8080");
});

客户端代码调整

省略冗余的子协议参数,保持代码简洁:

let webSocket = new WebSocket("ws://localhost:8080?chatId=15432");

额外注意:如果是直接本地打开HTML文件(file://协议),浏览器Origin会是null,此时需要确保服务器allowedOrigins包含"null";更推荐用本地HTTP服务器(比如npx serve)启动HTML文件,这样Origin会是标准的HTTP地址,更符合生产环境场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:45:38