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

如何在Node.js的HTTP路由与WebSocket服务器间实现内部消息通信?

问题描述

我有一个单片机(microcontroller)会向Node.js HTTP服务器发送数据,希望当该单片机触发HTTP请求时,通过WebSocket连接向Web客户端发送消息。

我的路由代码如下:

const express = require("express");
const router = express.Router();

router.route("/sendData").post(async (req, res) => {
   // 一些验证逻辑

   // 在这里我想发起一个消息,通过WebSocket发送给Web客户端

   return res.status(200).json({ message: "sent data to server"});
});

module.exports = router;

我的WebSocket服务器示例代码如下:

import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', function connection(ws) {
  // 我想在单片机触发HTTP请求时,向客户端发送消息
  ws.send('data received');
});

我是Node.js进程处理的新手,请问如何实现HTTP路由与WebSocket服务器之间的通信?是否需要使用node-ipc这类工具?


解决方案

不需要使用node-ipc这类跨进程通信工具,因为你的HTTP服务器和WebSocket服务器都运行在同一个Node.js进程里,直接共享变量就能实现通信。下面是具体实现步骤:

1. 共享WebSocket服务器实例

把WebSocket服务器(wss)的实例暴露出来,让Express路由能够访问到它。如果是拆分文件的结构,通过模块导出共享;如果是同一个文件,直接使用即可。

2. 在HTTP路由中遍历WebSocket连接发送消息

WebSocket服务器的wss.clients属性包含了所有当前活跃的客户端连接,你可以遍历这个集合,给每个客户端发送消息。注意要判断连接状态是否为打开(ws.readyState === ws.OPEN),避免向已关闭的连接发送消息。

3. 完整示例代码

方式一:整合到同一个文件

const express = require("express");
const { WebSocketServer } = require('ws');
const app = express();
const router = express.Router();

// 初始化WebSocket服务器
const wss = new WebSocketServer({ port: 8080 });

// 处理WebSocket连接
wss.on('connection', (ws) => {
  console.log('客户端已连接');
  ws.on('close', () => {
    console.log('客户端已断开');
  });
});

// HTTP路由
router.route("/sendData").post(async (req, res) => {
  // 执行你的验证逻辑
  const dataFromMCU = req.body; // 假设单片机发送的数据在请求体里

  // 遍历所有WebSocket客户端,发送消息
  wss.clients.forEach((client) => {
    if (client.readyState === client.OPEN) {
      client.send(JSON.stringify({
        type: 'MCU_DATA',
        data: dataFromMCU,
        timestamp: Date.now()
      }));
    }
  });

  return res.status(200).json({ message: "数据已接收,并已推送给WebSocket客户端" });
});

// 挂载路由
app.use(express.json()); // 解析JSON请求体
app.use('/api', router);

// 启动HTTP服务器
app.listen(3000, () => {
  console.log('HTTP服务器运行在3000端口');
});

方式二:拆分到不同文件(模块化)

websocket.js

const { WebSocketServer } = require('ws');

const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', (ws) => {
  console.log('客户端已连接');
  ws.on('close', () => {
    console.log('客户端已断开');
  });
});

// 导出WebSocket服务器实例
module.exports = wss;

routes/sendData.js

const express = require("express");
const router = express.Router();
const wss = require('../websocket'); // 导入WebSocket服务器实例

router.route("/sendData").post(async (req, res) => {
  // 验证逻辑
  const dataFromMCU = req.body;

  // 发送消息给所有WebSocket客户端
  wss.clients.forEach((client) => {
    if (client.readyState === client.OPEN) {
      client.send(JSON.stringify({
        source: 'MCU',
        data: dataFromMCU
      }));
    }
  });

  return res.status(200).json({ message: "数据已处理并推送" });
});

module.exports = router;

app.js

const express = require("express");
const app = express();
const sendDataRouter = require('./routes/sendData');

app.use(express.json());
app.use('/api', sendDataRouter);

app.listen(3000, () => {
  console.log('HTTP服务器运行在3000端口');
});

额外提示

  • 如果需要向特定客户端发送消息(而非所有客户端),可以在客户端连接时记录客户端的标识(比如通过客户端发送的ID),存储在一个Map里,之后根据标识找到对应的连接发送消息。
  • 要处理WebSocket连接的错误和关闭事件,避免内存泄漏。
  • 如果你的HTTP服务器和WebSocket服务器想使用同一个端口,可以利用Express的HTTP服务器实例来挂载WebSocket服务器,这样客户端只需要连接一个端口即可:
    const httpServer = app.listen(3000);
    const wss = new WebSocketServer({ server: httpServer });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 04:55:32