如何在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
相关产品推荐
相关产品推荐

