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

如何在Express中同时处理HTTP请求与Socket.IO连接?

Express与Socket.IO共存的正确实现方案

核心问题原因

Socket.IO的连接握手请求会先经过Express的中间件链,你设置的app.all("*")通配路由会拦截所有未匹配的HTTP请求,包括Socket.IO命名空间的握手请求,从而触发404错误。

解决方案步骤

1. 用HTTP Server同时挂载Express和Socket.IO

必须通过http.createServer创建HTTP服务器,同时挂载Express应用和Socket.IO,不能直接用app.listen()启动服务。

import express from 'express';
import { createServer } from 'http';
import { Server } from 'socket.io';

const app = express();
// 创建HTTP服务器并绑定Express
const httpServer = createServer(app);
// 初始化Socket.IO并挂载到HTTP服务器
const io = new Server(httpServer, { cors: { origin: "*" } });

// 处理/socket命名空间的连接事件
io.of("/socket").on("connection", (socket) => {
  console.log('客户端已连接到/socket命名空间');
  
  // 示例:监听客户端消息事件
  socket.on('sendMsg', (data) => {
    console.log('收到客户端消息:', data);
    socket.emit('recvMsg', '服务器已接收你的消息');
  });

  socket.on('disconnect', () => {
    console.log('客户端断开连接');
  });
});

2. 在Express通配路由前添加跳过逻辑

在app.all("*")之前,新增一个中间件,判断请求路径是否属于Socket.IO的命名空间,若是则跳过后续Express中间件(包括404路由),直接交给Socket.IO处理。

// 跳过Socket.IO命名空间路径的Express处理
app.use((req, res, next) => {
  // 匹配你的Socket.IO命名空间路径(这里是/socket)
  if (req.path.startsWith('/socket')) {
    // 跳过后续路由中间件,转交Socket.IO处理
    return next('route');
  }
  next();
});

// 你的REST路由
app.use("/users", userRouter);
app.use("/products", productRouter);

// 404错误处理路由(必须放在所有路由之后)
app.all("*", async (req: Request, res: Response) => {
  throw new NotFoundError("route");
});

3. 启动HTTP服务器而非Express应用

最后启动的是HTTP服务器,而非直接启动Express应用:

const PORT = 3000;
httpServer.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
});

客户端连接示例

客户端需要指定对应的命名空间进行连接:

import { io } from 'socket.io-client';
// 连接到/socket命名空间
const socket = io('http://localhost:3000/socket');

// 示例:发送消息到服务器
socket.emit('sendMsg', 'Hello Socket.IO!');

// 接收服务器回复
socket.on('recvMsg', (data) => {
  console.log('服务器回复:', data);
});

关键注意事项

  • 必须使用httpServer.listen()启动服务,否则Socket.IO无法绑定到HTTP服务器完成握手。
  • 跳过逻辑的中间件必须放在所有REST路由和404路由之前,确保Socket.IO路径不会被Express拦截。
  • 生产环境中建议修改CORS配置,替换origin: "*"为具体允许的域名,避免安全风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:20:26