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

基于Node.js+React的类式Socket.io连接localhost返回404求助

问题分析与修复方案

问题描述

原本常规配置下能建立Socket.io连接,改用类式写法实现后,从localhost访问该连接返回404错误,目标是实现前端与服务端Socket.io成功连接,接收Alchemy SDK Notify Webhook的事件通知。

代码示例

import express, { Application, Request, Response } from 'express';
import * as dotenv from 'dotenv';
import cors from 'cors';
import morgan from 'morgan';
import bodyParser, { json } from 'body-parser';
import homeRouter from './routes/home/homeRouter';
import balanceRouter from './routes/balance/balanceRouter';
import { Server } from 'socket.io';
import http from 'http';
import AlchemyClient from './controller/watcher/watcher.controller';
import mongoose from 'mongoose';
dotenv.config();
const PORT: number = process.env.HTTP_PORT as unknown as number;
const DB_URI: string = process.env.DB_URI as string;
class MainServer {
  private app: Application;
  private server: http.Server;
  private io: Server;

  constructor() {
    this.app = express();
    this.server = http.createServer(this.app);
    this.io = new Server(this.server, {
      cors: {
        origin: 'http://localhost:3000',
        methods: ['GET', 'POST'],
      },
    });
    this.connectToDatabase();
    this.configApp();
    this.configureMiddleware();
    this.configureRoutes();
  }
  private configApp(): void {
    this.app.use(express.json());
    this.app.use(cors());
    this.app.use(bodyParser.json());
    this.app.use(morgan(':method :url :status :response-time ms - :res[content-length]'));
  }

  private async connectToDatabase() {
    try {
      await mongoose.connect(DB_URI);
      console.log('Server connected...');
    } catch (error) {
      console.error(error);
    }
  }

  private configureMiddleware() {
    this.app.use(express.json());
    this.app.use(express.urlencoded({ extended: true }));
  }

  private configureRoutes(): void {
    this.app.use('/', homeRouter);
    this.app.use('/balances', balanceRouter);
    // this.app.get('/api/start-socket-connection', this.startSocketConnection);
    this.app.post('/alchemyhook', (req, res) => {
      // notification received from Alchemy from the webhook. Let the clients know.
      AlchemyClient.notificationReceived(this.io, req);
      res.status(200).end();
    });
  }

  public start(port: number): void {
    this.app.listen(port, () => {
      console.log(`Server started on port ${port}`);
    });
    this.io.on('connection', (socket) => {
      console.log('Client connected');
      socket.on('disconnect', () => console.log('Client disconnected'));
      socket.on('register address', (msg) => {
        //send address to Alchemy to add to notification
        AlchemyClient.registerAddress(msg);
      });
    });
  }
}

const server = new MainServer();
server.start(PORT);

核心问题

你在start方法中启动的是Express的app实例,但Socket.io是绑定在this.server(由http.createServer(this.app)创建的HTTP服务器实例)上的。直接启动app实例会导致Socket.io无法监听WebSocket连接请求,前端访问时自然返回404。

修复方案

修改start方法,启动绑定了Socket.io的HTTP服务器实例,而非Express的app:

public start(port: number): void {
  // 替换this.app.listen为this.server.listen
  this.server.listen(port, () => {
    console.log(`Server started on port ${port}`);
  });
  this.io.on('connection', (socket) => {
    console.log('Client connected');
    socket.on('disconnect', () => console.log('Client disconnected'));
    socket.on('register address', (msg) => {
      AlchemyClient.registerAddress(msg);
    });
  });
}

额外优化建议

  • 移除冗余的中间件:configApp和configureMiddleware中重复添加了express.json(),保留一处即可,避免不必要的重复处理。
  • 前端连接验证:确保前端代码使用正确的连接方式,例如:
    import { io } from 'socket.io-client';
    const socket = io('http://localhost:你的端口号');
    
    Socket.io会自动处理默认的/socket.io路径请求,无需手动添加。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 20:17:05